341 lines
8.7 KiB
Plaintext
341 lines
8.7 KiB
Plaintext
/*
|
|
* Copyright (c) 2012, ETH Zurich. All rights reserved.
|
|
*
|
|
* This file is distributed under the terms in the attached LICENSE file.
|
|
* If you do not find this file, copies can be found by writing to:
|
|
* ETH Zurich D-INFK, Universitaestr. 6, CH-8092 Zurich. Attn: Systems Group.
|
|
*/
|
|
|
|
/*
|
|
* ohci.dev
|
|
*
|
|
* DESCRIPTION: Open Host Controller Interface (OHCI) description
|
|
*
|
|
* Archaic USB interface, but still found on e.g. ATI and NVidia
|
|
* chipsets.
|
|
*
|
|
* Numbers in comments refer to the OpenHCI Open Host Controller
|
|
* Interface Specification for USB, by Compaq, Microsoft, and National
|
|
* Semiconductor, 09/14/99 2:33 PM, Release: 1.0a
|
|
*/
|
|
|
|
|
|
device ohci lsbfirst ( addr base ) "OHCI USB controller" {
|
|
|
|
/*
|
|
//
|
|
// Data structures
|
|
//
|
|
|
|
// 4.2.1
|
|
constants direction width(2) "Data flow direction" {
|
|
dir_td = 0b00 "Get direction from TD";
|
|
dir_out = 0b01 "Out";
|
|
dir_in = 0b10 "In";
|
|
dir_td1 = 0b11 "Get direction from TD (alt)";
|
|
};
|
|
|
|
datatype epdesc lsbfirst(32) "Endpoint descriptor" {
|
|
fa 7 "Function address";
|
|
en 4 "Endpoint number";
|
|
d 2 type(direction) "Direction";
|
|
s 1 "Speed (1=low, 0=full)";
|
|
k 1 "Skip";
|
|
f 1 "Format (1=isochronous, 0=general)";
|
|
mps 11 "Maximum packet size";
|
|
_ 5;
|
|
_ 4;
|
|
tailp 28 "TD queue tail pointer";
|
|
h 1 "Halted";
|
|
c 1 "Toggle carry";
|
|
_ 2 mbz;
|
|
headp 28 "TD queue head pointer";
|
|
_ 4;
|
|
nexted 28 "Next endpoint descriptor";
|
|
};
|
|
|
|
// 4.3.1
|
|
constants pid width(2) "Direction / PID for token" {
|
|
pid_setup = 0b00 "Setup (to endpoint)";
|
|
pid_out = 0b01 "To endpoint";
|
|
pid_in = 0b10 "From endpoint";
|
|
};
|
|
datatype gentd lsbfirst(32) "General transfer descriptor" {
|
|
_ 18;
|
|
r 1 "Buffer rounding";
|
|
dp 2 type(pid) "Direction or PID";
|
|
di 3 "Delay interrupt frames";
|
|
t 2 "Data toggle";
|
|
ec 2 "Error count";
|
|
cc 4 type(ccode) "Condition code for last attempted transaction";
|
|
cbp 32 "Current buffer pointer";
|
|
_ 4 mbz;
|
|
nexttd 28 "Next transfer descriptor";
|
|
be 32 "Buffer end";
|
|
};
|
|
|
|
|
|
// 4.3.2
|
|
datatype isotd lsbfirst(32) "Isochronous transfer descriptor" {
|
|
sf 16 "Starting frame";
|
|
_ 5;
|
|
di 3 "Delay interrupt frames";
|
|
fc 3 "Frame count";
|
|
_ 1;
|
|
cc 4 type(ccode) "Condition code for last attempted transaction";
|
|
_ 12;
|
|
bp0 20 "Buffer page 0";
|
|
_ 5 mbz;
|
|
nexttd 27 "Next transfer descriptor";
|
|
be 32 "Buffer end";
|
|
ofpsw0 16 "Offset / packet status word 0";
|
|
ofpsw1 16 "Offset / packet status word 1";
|
|
ofpsw2 16 "Offset / packet status word 2";
|
|
ofpsw3 16 "Offset / packet status word 4";
|
|
ofpsw4 16 "Offset / packet status word 3";
|
|
ofpsw5 16 "Offset / packet status word 5";
|
|
ofpsw6 16 "Offset / packet status word 6";
|
|
ofpsw7 16 "Offset / packet status word 7";
|
|
};
|
|
datatype psw lsbfirst(16) "Packet status word" {
|
|
size 11 "Size of packet";
|
|
_ 1 mbz;
|
|
cc 4 type(ccode) "Condition code";
|
|
};
|
|
|
|
/// 4.3.3
|
|
constants ccode width(4) "Completion codes" {
|
|
cc_ne = 0b0000 "No error";
|
|
cc_crc = 0b0001 "CRC error";
|
|
cc_bs = 0b0010 "Bitstuffing violation";
|
|
cc_dtm = 0b0011 "Data toggle PID mismatch";
|
|
cc_stl = 0b0100 "EP returned stall PID";
|
|
cc_dnr = 0b0101 "Device not responding";
|
|
cc_pcf = 0b0110 "PID check failure";
|
|
cc_uxp = 0b0111 "Unexpected PID";
|
|
cc_dor = 0b1000 "Data overrun";
|
|
cc_dur = 0b1001 "Data underrun";
|
|
cc_bor = 0b1100 "Buffer overrun";
|
|
cc_bur = 0b1101 "Buffer underrun";
|
|
cc_nac = 0b1110 "Not accessed";
|
|
cc_nac_ = 0b1111 "Not accessed (alternate)";
|
|
};
|
|
*/
|
|
//
|
|
// Registers
|
|
//
|
|
// 7.1 Control and status partition
|
|
//
|
|
|
|
// 7.1.1 Interface revision
|
|
/// Initially 0x10.
|
|
register revision ro addr (base, 0x00) "Revision" {
|
|
rev 8 "BCD rep. of interface version";
|
|
_ 24;
|
|
};
|
|
|
|
// 7.1.2 Control register
|
|
constants state "Functional state" {
|
|
st_reset = 0b00 "Reset (after h/w reset)";
|
|
st_resume = 0b01 "Resume from downstream port";
|
|
st_operational = 0b10 "Operational (running)";
|
|
st_suspend = 0b11 "Suspend (after s/w reset)";
|
|
};
|
|
// Initially 0x00
|
|
register control rw addr (base, 0x04) "Control" {
|
|
cbsr 2 "Control/bulk service ratio";
|
|
pe 1 "Periodic list enable";
|
|
ie 1 "Isochronous enable";
|
|
cle 1 "Control list enable";
|
|
ble 1 "Bulk list enable";
|
|
hcfs 2 type(state) "Host controller functional state";
|
|
ir 1 "Interrupt routing";
|
|
rwc 1 "Remote wakeup connected";
|
|
rwe 1 "Remote wakeup enabled";
|
|
_ 21;
|
|
};
|
|
|
|
|
|
// 7.1.3 Command and Status
|
|
// Initially 0x00
|
|
register cmdstatus rw addr (base, 0x08) "08 CommandStatus" {
|
|
hcr 1 "Host controller reset";
|
|
clf 1 "Control list filled";
|
|
blf 1 "Bulk list filled";
|
|
ocr 1 "Ownership change request";
|
|
_ 12;
|
|
soc 2 ro "Scheduling overrun count";
|
|
_ 14;
|
|
};
|
|
|
|
// 7.1.4-6: Interrupt registers
|
|
regtype interrupt "Interrupts" {
|
|
so 1 "Scheduling overrun";
|
|
wdh 1 "Writeback done head";
|
|
sf 1 "Start of frame";
|
|
rd 1 "Resume detected";
|
|
ue 1 "Unrecoverable error";
|
|
fno 1 "Frame number overflow";
|
|
rhsc 1 "Root hub status change";
|
|
_ 23;
|
|
oc 1 "Ownership change";
|
|
mie 1 "Master interrupt enable";
|
|
};
|
|
register intstatus rw addr (base, 0x0C) "Interrupt status"
|
|
type(interrupt);
|
|
register intenable rw addr (base, 0x10) "Interrupt enable"
|
|
type(interrupt);
|
|
register intdisable rw addr (base, 0x14) "Interrupt disable"
|
|
type(interrupt);
|
|
|
|
//
|
|
// 7.2 Memory pointer partition
|
|
//
|
|
|
|
// 7.2.1
|
|
register hcca rw addr (base, 0x18) "Host controller communication area" {
|
|
_ 8 mbz;
|
|
hcca 24 "Physical address";
|
|
};
|
|
|
|
regtype physptr "Physical address pointer" {
|
|
_ 4 mbz;
|
|
addr 28 "Address";
|
|
};
|
|
|
|
// 7.2.2.
|
|
register period_cur ro addr (base, 0x1C) "Cur. isochronous or int. ED"
|
|
type(physptr);
|
|
|
|
// 7.2.3
|
|
register ctrl_head rw addr (base, 0x20) "First ED of control list"
|
|
type(physptr);
|
|
|
|
|
|
// 7.2.4
|
|
register ctrl_cur rw addr (base, 0x24) "Current ED of control list"
|
|
type(physptr);
|
|
|
|
// 7.2.5
|
|
register bulk_head rw addr (base, 0x28) "First ED of bulk list"
|
|
type(physptr);
|
|
|
|
// 7.2.6
|
|
register bulk_cur rw addr (base, 0x2C) "Current ED of bulk list"
|
|
type(physptr);
|
|
|
|
|
|
// 7.2.7
|
|
register done_head ro addr (base, 0x30) "Done head pointer"
|
|
type(physptr);
|
|
|
|
//
|
|
// 7.3 Frame counter partition
|
|
//
|
|
|
|
// 7.3.1
|
|
register fm_interval rw addr (base, 0x34) "Frame interval" {
|
|
fi 14 "Frame interval (dflt 0x2edf)";
|
|
_ 2;
|
|
fsmps 15 "FS largest data packet";
|
|
fit 1 "Frame interval toggle";
|
|
};
|
|
|
|
// 7.3.2
|
|
register fm_remain ro addr (base, 0x38) "Frame remaining" {
|
|
fr 14 "Bit time remaining in current frame";
|
|
_ 17;
|
|
frt 1 "Frame remaining toggle";
|
|
};
|
|
|
|
// 7.3.3
|
|
register fm_num ro addr (base, 0x3C) "Frame number" {
|
|
fn 16 "Frame number (16-bit counter)";
|
|
_ 16;
|
|
};
|
|
|
|
// 7.3.4
|
|
register period_start rw addr (base, 0x40) "Period start" {
|
|
ps 14 "Start time for processing periodic list";
|
|
_ 18;
|
|
};
|
|
|
|
// 7.3.5
|
|
register hclsthreshold rw addr (base, 0x44) "LS threshold" {
|
|
lst 11 "Low-speed threshold (should be 0x0628)";
|
|
_ 21;
|
|
};
|
|
|
|
//
|
|
// 7.4 Root Hub partition
|
|
//
|
|
|
|
// 7.4.1
|
|
register rh_descra rw addr (base, 0x48) "Root hub descriptor a" {
|
|
ndp 8 ro "Number of downstream ports";
|
|
psm 1 "Power switching mode";
|
|
nps 1 "No power switching";
|
|
dt 1 ro "Device type";
|
|
ocpm 1 "Overcurrent protection mode";
|
|
nocp 1 "No overcurrent protection";
|
|
_ 11;
|
|
potpgt 8 "Power-on to power-good time (* 2ms)";
|
|
};
|
|
|
|
// 7.4.2
|
|
register rh_descrb rw addr (base, 0x4C) "Root hub descriptor b" {
|
|
dr 16 "Device removal";
|
|
ppcm 16 "Port power control mask";
|
|
};
|
|
|
|
// 7.4.3
|
|
register rh_status rw addr (base, 0x50) "Root hub status" {
|
|
lps 1 wo "Clear global power";
|
|
oci 1 ro "Overcurrent indicator";
|
|
_ 13;
|
|
drwe 1 rw1c "Device remote wakeup enable";
|
|
lpsc 1 wo "Set globl power";
|
|
ocic 1 rw1c "Overcurrent indicator change";
|
|
_ 13;
|
|
crwe 1 wo "Clear remote wakeup enable";
|
|
};
|
|
|
|
// 7.4.4
|
|
// Assume 256 ports at this stage; it's actually given by
|
|
// rh_descra->ndp.
|
|
regarray rh_portstat ro addr (base, 0x54)[256] "Root hub port status" {
|
|
ccs 1 "Current connection status";
|
|
pes 1 "Port enable status";
|
|
pss 1 "Port suspend status";
|
|
poci 1 "Port overcurrent indicator";
|
|
prs 1 "Port reset status";
|
|
_ 3;
|
|
pps 1 "Port power status";
|
|
lsda 1 "Low-speed device attached";
|
|
_ 6;
|
|
csc 1 "Connect status change";
|
|
pesc 1 "Port enable status change";
|
|
pssc 1 "Port suspend status change";
|
|
ocic 1 "Port overcurrent indicator change";
|
|
prsc 1 "Port reset status change";
|
|
_ 11;
|
|
};
|
|
regarray rh_portctrl wo also addr (base, 0x54)[256] "Root hub port control" {
|
|
cpe 1 "Clear port enable";
|
|
spe 1 "Set port enable";
|
|
sps 1 "Set port suspend";
|
|
css 1 "Clear suspend status";
|
|
spr 1 "Set port reset";
|
|
_ 3;
|
|
spp 1 "Set port power";
|
|
cpp 1 "Clear port power";
|
|
_ 6;
|
|
csc 1 "Clear connect status change";
|
|
pesc 1 "Clear port enable status change";
|
|
pssc 1 "Clear port suspend status change";
|
|
ocic 1 "Clear port overcurrent indicator change";
|
|
prsc 1 "Clear port reset status change";
|
|
_ 11;
|
|
};
|
|
};
|