Skip to content

Commit

Permalink
Add runtime registers, testing for TLB to XHCI
Browse files Browse the repository at this point in the history
  • Loading branch information
jackpot51 committed Jul 24, 2017
1 parent 513ddd9 commit 815b59b
Show file tree
Hide file tree
Showing 5 changed files with 289 additions and 19 deletions.
6 changes: 4 additions & 2 deletions xhcid/src/main.rs
@@ -1,3 +1,5 @@
#![feature(core_intrinsics)]

#[macro_use]
extern crate bitflags;
extern crate syscall;
Expand All @@ -22,7 +24,7 @@ fn main() {
// Daemonize
if unsafe { syscall::clone(0).unwrap() } == 0 {
let address = unsafe { syscall::physmap(bar, 4096, syscall::MAP_WRITE).expect("xhcid: failed to map address") };
/*

match Xhci::new(address) {
Ok(mut xhci) => {
xhci.init();
Expand All @@ -31,7 +33,7 @@ fn main() {
println!("xhcid: error: {}", err);
}
}
*/

unsafe { let _ = syscall::physunmap(address); }
}
}
8 changes: 8 additions & 0 deletions xhcid/src/xhci/event.rs
@@ -0,0 +1,8 @@
use syscall::io::Mmio;

pub struct EventRingSte {
pub address: Mmio<u64>,
pub size: Mmio<u16>,
_rsvd: Mmio<u16>,
_rsvd2: Mmio<u32>,
}
69 changes: 52 additions & 17 deletions xhcid/src/xhci.rs → xhcid/src/xhci/mod.rs
Expand Up @@ -2,22 +2,11 @@ use std::slice;
use syscall::error::Result;
use syscall::io::{Dma, Mmio, Io};

#[repr(packed)]
struct Trb {
pub data: u64,
pub status: u32,
pub control: u32,
}
mod event;
mod trb;

impl Trb {
pub fn from_type(trb_type: u32) -> Self {
Trb {
data: 0,
status: 0,
control: (trb_type & 0x3F) << 10,
}
}
}
use self::event::*;
use self::trb::*;

#[repr(packed)]
pub struct XhciCap {
Expand Down Expand Up @@ -46,6 +35,21 @@ pub struct XhciOp {
config: Mmio<u32>,
}

pub struct XhciInterrupter {
iman: Mmio<u32>,
imod: Mmio<u32>,
erstsz: Mmio<u32>,
_rsvd: Mmio<u32>,
erstba: Mmio<u64>,
erdp: Mmio<u64>,
}

pub struct XhciRun {
mfindex: Mmio<u32>,
_rsvd: [Mmio<u32>; 7],
ints: [XhciInterrupter; 1024],
}

bitflags! {
flags XhciPortFlags: u32 {
const PORT_CCS = 1 << 0,
Expand Down Expand Up @@ -131,9 +135,11 @@ pub struct Xhci {
op: &'static mut XhciOp,
ports: &'static mut [XhciPort],
dbs: &'static mut [XhciDoorbell],
run: &'static mut XhciRun,
dev_baa: Dma<[u64; 256]>,
dev_ctxs: Vec<Dma<XhciDeviceContext>>,
cmds: Dma<[Trb; 256]>,
event_rings: Dma<[EventRingSte; 1]>,
}

impl Xhci {
Expand Down Expand Up @@ -175,17 +181,22 @@ impl Xhci {
let port_base = op_base + 0x400;
let ports = unsafe { slice::from_raw_parts_mut(port_base as *mut XhciPort, max_ports as usize) };

let db_base = op_base + cap.db_offset.read() as usize;
let db_base = address + cap.db_offset.read() as usize;
let dbs = unsafe { slice::from_raw_parts_mut(db_base as *mut XhciDoorbell, 256) };

let run_base = address + cap.rts_offset.read() as usize;
let run = unsafe { &mut *(run_base as *mut XhciRun) };

let mut xhci = Xhci {
cap: cap,
op: op,
ports: ports,
dbs: dbs,
run: run,
dev_baa: Dma::zeroed()?,
dev_ctxs: Vec::new(),
cmds: Dma::zeroed()?,
event_rings: Dma::zeroed()?,
};

{
Expand All @@ -200,7 +211,10 @@ impl Xhci {
xhci.op.dcbaap.write(xhci.dev_baa.physical() as u64);

// Set command ring control register
xhci.op.crcr.write(xhci.cmds.physical() as u64);
xhci.op.crcr.write(xhci.cmds.physical() as u64 | 1);

// Set event ring segment table registers
//TODO

// Set run/stop to 1
xhci.op.usb_cmd.writef(1, true);
Expand All @@ -209,6 +223,9 @@ impl Xhci {
while xhci.op.usb_sts.readf(1) {
println!(" - Waiting for XHCI running");
}

// Ring command doorbell
xhci.dbs[0].write(0);
}

Ok(xhci)
Expand All @@ -222,5 +239,23 @@ impl Xhci {
let flags = port.flags();
println!(" + XHCI Port {}: {:X}, State {}, Speed {}, Flags {:?}", i, data, state, speed, flags);
}

self.cmds[0].no_op_cmd(true);

println!("Before");
println!("USBSTS: {:X}", self.op.usb_sts.read());
println!("CRCR: {:X}", self.op.crcr.read());
println!("data: {:X}", self.cmds[0].data.read());
println!("status: {:X}", self.cmds[0].status.read());
println!("control: {:X}", self.cmds[0].control.read());

self.dbs[0].write(0);

println!("After");
println!("USBSTS: {:X}", self.op.usb_sts.read());
println!("CRCR: {:X}", self.op.crcr.read());
println!("data: {:X}", self.cmds[0].data.read());
println!("status: {:X}", self.cmds[0].status.read());
println!("control: {:X}", self.cmds[0].control.read());
}
}
102 changes: 102 additions & 0 deletions xhcid/src/xhci/termios.rs
@@ -0,0 +1,102 @@
use std::cell::RefCell;
use std::ops::{Deref, DerefMut};
use std::rc::Weak;

use syscall::error::{Error, Result, EBADF, EINVAL, EPIPE};
use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE};

use pty::Pty;
use resource::Resource;

/// Read side of a pipe
#[derive(Clone)]
pub struct PtyTermios {
pty: Weak<RefCell<Pty>>,
flags: usize,
}

impl PtyTermios {
pub fn new(pty: Weak<RefCell<Pty>>, flags: usize) -> Self {
PtyTermios {
pty: pty,
flags: flags,
}
}
}

impl Resource for PtyTermios {
fn boxed_clone(&self) -> Box<Resource> {
Box::new(self.clone())
}

fn pty(&self) -> Weak<RefCell<Pty>> {
self.pty.clone()
}

fn flags(&self) -> usize {
self.flags
}

fn path(&self, buf: &mut [u8]) -> Result<usize> {
if let Some(pty_lock) = self.pty.upgrade() {
pty_lock.borrow_mut().path(buf)
} else {
Err(Error::new(EPIPE))
}
}

fn read(&self, buf: &mut [u8]) -> Result<usize> {
if let Some(pty_lock) = self.pty.upgrade() {
let pty = pty_lock.borrow();
let termios: &[u8] = pty.termios.deref();

let mut i = 0;
while i < buf.len() && i < termios.len() {
buf[i] = termios[i];
i += 1;
}
Ok(i)
} else {
Ok(0)
}
}

fn write(&self, buf: &[u8]) -> Result<usize> {
if let Some(pty_lock) = self.pty.upgrade() {
let mut pty = pty_lock.borrow_mut();
let termios: &mut [u8] = pty.termios.deref_mut();

let mut i = 0;
while i < buf.len() && i < termios.len() {
termios[i] = buf[i];
i += 1;
}
Ok(i)
} else {
Err(Error::new(EPIPE))
}
}

fn sync(&self) -> Result<usize> {
Ok(0)
}

fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize> {
match cmd {
F_GETFL => Ok(self.flags),
F_SETFL => {
self.flags = (self.flags & O_ACCMODE) | (arg & ! O_ACCMODE);
Ok(0)
},
_ => Err(Error::new(EINVAL))
}
}

fn fevent(&self) -> Result<()> {
Err(Error::new(EBADF))
}

fn fevent_count(&self) -> Option<usize> {
None
}
}
123 changes: 123 additions & 0 deletions xhcid/src/xhci/trb.rs
@@ -0,0 +1,123 @@
use syscall::io::{Io, Mmio};

#[repr(u8)]
pub enum TrbType {
Reserved,
/* Transfer */
Normal,
SetupStage,
DataStage,
StatusStage,
Isoch,
Link,
EventData,
NoOp,
/* Command */
EnableSlot,
DisableSlot,
AddressDevice,
ConfigureEndpoint,
EvaluateContext,
ResetEndpoint,
StopEndpoint,
SetTrDequeuePointer,
ResetDevice,
ForceEvent,
NegotiateBandwidth,
SetLatencyToleranceValue,
GetPortBandwidth,
ForceHeader,
NoOpCmd,
/* Reserved */
Rsv24,
Rsv25,
Rsv26,
Rsv27,
Rsv28,
Rsv29,
Rsv30,
Rsv31,
/* Events */
Transfer,
CommandCompletion,
PortStatusChange,
BandwidthRequest,
Doorbell,
HostController,
DeviceNotification,
MfindexWrap,
/* Reserved from 40 to 47, vendor devined from 48 to 63 */
}

#[repr(u8)]
pub enum TrbCompletionCode {
Invalid,
Success,
DataBuffer,
BabbleDetected,
UsbTransaction,
Trb,
Stall,
Resource,
Bandwidth,
NoSlotsAvailable,
InvalidStreamType,
SlotNotEnabled,
EndpointNotEnabled,
ShortPacket,
RingUnderrun,
RingOverrun,
VfEventRingFull,
Parameter,
BandwidthOverrun,
ContextState,
NoPingResponse,
EventRingFull,
IncompatibleDevice,
MissedService,
CommandRingStopped,
CommandAborted,
Stopped,
StoppedLengthInvalid,
StoppedShortPacket,
MaxExitLatencyTooLarge,
Rsv30,
IsochBuffer,
EventLost,
Undefined,
InvalidStreamId,
SecondaryBandwidth,
SplitTransaction,
/* Values from 37 to 191 are reserved */
/* 192 to 223 are vendor defined errors */
/* 224 to 255 are vendor defined information */
}

#[repr(packed)]
pub struct Trb {
pub data: Mmio<u64>,
pub status: Mmio<u32>,
pub control: Mmio<u32>,
}

impl Trb {
pub fn reset(&mut self, param: u64, status: u32, control: u16, trb_type: TrbType, evaluate_next: bool, cycle: bool) {
let full_control =
(control as u32) << 16 |
((trb_type as u32) & 0x3F) << 10 |
if evaluate_next { 1 << 1 } else { 0 } |
if cycle { 1 << 0 } else { 0 };

self.data.write(param);
self.status.write(status);
self.control.write(full_control);
}

pub fn no_op_cmd(&mut self, cycle: bool) {
self.reset(0, 0, 0, TrbType::NoOpCmd, false, cycle);
}

pub fn enable_slot(&mut self, slot_type: u8, cycle: bool) {
self.reset(0, 0, (slot_type as u16) & 0x1F, TrbType::EnableSlot, false, cycle);
}
}

0 comments on commit 815b59b

Please sign in to comment.