Commit 815b59b8 authored by Jeremy Soller's avatar Jeremy Soller

Add runtime registers, testing for TLB to XHCI

parent 513ddd9e
#![feature(core_intrinsics)]
#[macro_use]
extern crate bitflags;
extern crate syscall;
......@@ -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();
......@@ -31,7 +33,7 @@ fn main() {
println!("xhcid: error: {}", err);
}
}
*/
unsafe { let _ = syscall::physunmap(address); }
}
}
use syscall::io::Mmio;
pub struct EventRingSte {
pub address: Mmio<u64>,
pub size: Mmio<u16>,
_rsvd: Mmio<u16>,
_rsvd2: Mmio<u32>,
}
......@@ -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 {
......@@ -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,
......@@ -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 {
......@@ -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()?,
};
{
......@@ -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);
......@@ -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)
......@@ -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());
}
}
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
}
}
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);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment