/* * Copyright (c) 2009, 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, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. */ /* * ehci.dev * * DESCRIPTION: Enhanced Host Controller Interface description * * Numbers in comments refer to the Intel Enhanced Host Controller * Interface Specification for Universal Serial Bus, March 12, 2002, * Revision: 1.0 */ device ehci msbfirst (addr cap, addr op) "EHCI USB Controller" { /* * Section 2.2 * Host controller capabilty registers */ // 2.2.1 // The correct value for 'op' is actually 'cap' plus this number. register caplength ro addr(cap, 0x00) "Capability Registers Length" type(uint8); // 2.2.2 register hciversion ro addr(cap, 0x02) "Host Controller Interface Version Number" type(uint16); // 2.2.3 register hcsparams ro addr(cap, 0x04) "Structural parameters" { _ 8; dpn 4 "Debug port number"; _ 3; p_indicator 1 "Port indicator"; n_cc 4 "Number of campanion controller"; n_pcc 4 "Number of ports per companion controller"; prr 1 "Port routing rules"; _ 2; ppc 1 "Port power control"; n_ports 4 "Num. physical downstream ports on this controller"; }; // 2.2.4 register hccparams ro addr(cap, 0x08) "Capability parameters" { _ 16; eecp 8 "EHCI extended capabilities pointer"; ist 4 "Isochronous scheduling threshold"; _ 1; aspc 1 "Asynchronous sechedule park capability"; pflf 1 "Programmable frame list flag"; bit64ac 1 "Extended 64 bit addressing capability"; }; // section 2.2.5 Companion port route descriptor register hcspportroute ro addr(cap, 0x0C) "Companion port route descr." { attr 60 "Port array"; _ 4; }; /* * Section 2.3 * Host controller operational registers */ constants itc_val "Interrupt threshold control" { itc_val_rsvd = 0x00 "Reserved"; uframe_1 = 0x01 "1 Micro frame"; uframes_2 = 0x02 "2 Micro frames"; uframes_4 = 0x04 "4 Micro frames"; uframes_8 = 0x08 "8 Micro frames (default, equates to 1 ms)"; uframes_16 = 0x10 "16 Micro frames (2 ms)"; uframes_32 = 0x20 "32 Micro frames (4 ms)"; uframes_64 = 0x40 "64 Micro frames (8 ms)"; }; constants frame_val "Frame list size" { elem_1024 = 0b00 "1024 Elements (4096 bytes, default)"; elem_512 = 0b01 "512 Elements (2048 bytes)"; elem_256 = 0b10 "256 Elements (1024 bytes)"; frame_rsvd = 0b11 "Reserved"; }; // 2.3.1 register usbcmd rw addr(op, 0x00) "USB command" { _ 8 mbz; itc 8 type(itc_val) "Interrupt threshold control"; _ 4 mbz; aspme 1 rw "Asynchronous schedule park mode enable"; _ 1 mbz; aspmc 2 rw "Asynchronous schedule park mode count"; lhcr 1 rw "Light host controller reset"; iaad 1 rw "Interrupt on async advance doorbell"; ase 1 rw "Asynchronous schedule enable"; pse 1 rw "Periodic schedule enable"; fls 2 type(frame_val) "Frame list size"; hcr 1 rw "Host controller reset"; rs 1 rw "Run stop for scheduling"; }; // 2.3.2 register usbsts rw addr(op, 0x04) "USB status" { _ 16 mbz; ass 1 ro "Asynchronous schedule status"; pss 1 ro "Periodic schedule status"; rec 1 ro "Reclamation"; hch 1 ro "Host controller halted see Run/Stop"; _ 6 mbz; iaa 1 rwc "Interrupt on Async advance"; hse 1 rwc "Host system error"; flr 1 rwc "Frame list rollover"; pcd 1 rwc "Port change detect"; usbei 1 rwc "USB error interrupt"; usbi 1 rwc "USB interrupt"; }; // 2.3.3 register usbintr rw addr(op, 0x08) "USB interrupt enable" { _ 26 mbz; iaae 1 "Interrupt on async advance enable"; hsee 1 "Host system error enable"; flre 1 "Frame list rollover enable"; pcie 1 "Port change interrupt enable"; usbeie 1 "USB error interrupt enable"; usbie 1 "USB interrupt enable"; }; // 2.3.4 register frindex rw addr(op, 0x0C) "Frame index" { _ 18 mbz; fi 14 "Frame index"; }; // 2.3.5 // NOTE: Only enabled if 64 bit address capability is enabled register ctrldssegment rw addr(op, 0x10) "Control data structure segment" { data 32 rw "MSB [63:32] bits of EHCI data strctures"; }; // 2.3.6 register periodiclistbase rw addr(op, 0x14) "Periodic frame list base addr" { addr 20 rw "Base address (must be 4k aligned)"; _ 12 mbz; }; // 2.3.7 register asynclistaddr rw addr(op, 0x18) "Current async. list addr." { lpl 27 rw "Link pointer low"; _ 5 mbz; }; // 2.3.8 register configflag rw addr(op, 0x40) "Configure flag" { _ 31 mbz; cf 1 rw "Configure flag"; }; // 2.3.9 constants test_mode_val "Test modes" { disabled = 0b0000 "Test mode not enabled"; test_j_st = 0b0001 "Test J_STATE"; test_k_st = 0b0010 "Test K_STATE"; se0_nak = 0b0011 "Test SE0_NAK"; test_pack = 0b0100 "Test packet"; force_ena = 0b0101 "Force enable"; }; constants indi_val "Port indicator values" { off = 0b00 "Port indicators are off"; amber = 0b01 "Amber"; green = 0b10 "Green"; indi_val_undef = 0b11 "Undefined"; }; constants lstatus_val "USB line status" { se0 = 0b00 "Not low speed device, perform EHCI reset"; j_state = 0b10 "Not low speed device, perform EHCI reset"; k_state = 0b01 "Low speed device, release ownership of port"; lstatus_undef = 0b11 "Not low speed device, perform EHCI reset"; }; regarray portsc rw addr(op, 0x44)[16] "Port status and control" { _ 9 mbz; wkoc_e 1 "Wake on over-current enable"; wkdscnnt_e 1 "Wake on disconnect enable"; wkcnnt_e 1 "Wake on connect enable"; ptc 4 type(test_mode_val) "Port test control"; pic 2 type(indi_val) "Port indicator control"; po 1 "Port owner"; pp 1 "Port power"; ls 2 type(lstatus_val) "Line status value"; _ 1 mbz; pr 1 "Port reset"; sus 1 "Port suspend"; fpr 1 "Force port resume"; occ 1 rwc "Over current change"; oca 1 ro "Over current active"; pec 1 rwc "Port enable/disbale change"; ped 1 "Port enabled/disabled"; csc 1 rwc "Connect status change"; ccs 1 ro "Current connect status"; }; /* // // In-memory data structures // // 3.1 constants lptype width(2) "Link pointer type" { lp_itd = 0b00 "Isochronous transfer descriptor"; lp_qh = 0b01 "Queue head"; lp_sitd = 0b10 "Split transaction isochronous trans. desc."; lp_fstn = 0b11 "Frame span traversal node"; }; datatype lp msbfirst(32) "Link pointer" { p 27 "Frame list link pointer"; _ 2 mbz; typ 2 type(lptype) "Pointer type"; t 1 "Pointer value invalid"; }; // 3.3 datatype itd msbfirst(32) "Isochronous transfer descriptor" { next 32 type(lp) "Next descriptor"; sc0 32 type(itsc) "Transaction 0 Status/control"; sc1 32 type(itsc) "Transaction 1 Status/control"; sc2 32 type(itsc) "Transaction 2 Status/control"; sc3 32 type(itsc) "Transaction 3 Status/control"; sc4 32 type(itsc) "Transaction 4 Status/control"; sc5 32 type(itsc) "Transaction 5 Status/control"; sc6 32 type(itsc) "Transaction 6 Status/control"; sc7 32 type(itsc) "Transaction 7 Status/control"; bp0 32 type(itbp0) "Buffer pointer 0"; bp1 32 type(itbp1) "Buffer pointer 1"; bp2 32 type(itbp2) "Buffer pointer 2"; bp3 32 type(itbp3) "Buffer pointer 3"; bp4 32 type(itbp3) "Buffer pointer 4"; bp5 32 type(itbp3) "Buffer pointer 5"; bp6 32 type(itbp3) "Buffer pointer 6"; }; // 3.3.2 datatype itsc msbfirst(32) "Isochronous transaction status/control" { // Status active 1 "Active"; dbe 1 "Data buffer error"; bd 1 "Babble detected"; xacterr 1 "Transaction error"; // Control length 12 "Transaction length"; ioc 1 "Interrupt on complete"; pg 3 "Page select (0-6)"; offset 12 "Offset from state of buffer"; }; // 3.3.3 datatype itbp0 msbfirst(32) "iTD buffer pointer page 0" { p 20 "Buffer pointer (4k aligned)"; epn 4 "Endpoint number"; _ 1 mbz; da 7 "Device address"; }; datatype itdp1 msbfirst(32) "iTD buffer pointer page 1" { p 20 "Buffer pointer (4k aligned)"; dir 1 "In (1) or out (0) PID"; mps 11 "Maximum packet size"; }; datatype itdp2 msbfirst(32) "iTD buffer pointer page 2" { p 20 "Buffer pointer (4k aligned)"; _ 10 mbz; multi 2 "Num. transactions/micro-frame + 1 (0=rsvd)"; }; datatype itdp3 msbfirst(32) "iTD buffer pointer page 3" { p 20 "Buffer pointer (4k aligned)"; _ 12 mbz; }; // 3.4 datatype sitd msbfirst(32) "Split isochronous transfer descriptor" { next 32 type(lp) "Next descriptor"; cap 32 type(sitcap) "Endpoint capabilities/characteristics"; msc 32 type(sitmsc) "Micro-frame schedule control"; tsc 32 type(sittsc) "Transfer status and control"; bpl0 32 type(sitbpl0) "Buffer page pointer 0"; bpl1 32 type(sitbpl1) "Buffer page pointer 1"; bp 32 type(sitblp) "Back link"; }; // 3.4.2 datatype sitcap msbfirst(32) "siTD endpoint capabilities/characteristics" { dir 1 "In (1) or out (0) PID"; port 7 "Port number"; _ 1 mbz; hub 7 "Hub address"; _ 4 mbz; epn 4 "Endpoint number"; _ 1 mbz; da 7 "Device address"; }; datatype sitmsc msbfirst(32) "siTD micro-frame schedule control" { _ 16 mbz; scm 8 "Split completion mask"; ssm 8 "Split start mask"; }; // 3.4.3 datatype sittsc msbfirst(32) "siTD transfer status and control" { ioc 1 "Interrupt on complete"; p 1 "Page select"; _ 4 mbz; total 10 "Total bytes to transfer"; cpm 8 "Microframe complete-split progress mask"; active 1 "Status active"; err 1 "ERR response rcvd from transaction translator"; dbe 1 "Data buffer error"; babble 1 "Babble detected"; xacterr 1 "Transaction error"; mmf 1 "Missed micro-frame"; sts 1 "Split transaction state"; _ 1 mbz; }; // 3.4.4 constants xpos width(2) "Transaction position" { tp_all = 0b00 "Entire payload"; tp_begin = 0b01 "First data payload"; tp_mid = 0b10 "Middle payload"; tp_end = 0b11 "Final payload"; }; datatype sitbpl0 msbfirst(32) "siTD buffer page pointer list page 0" { p 20 "Buffer pointer (4k aligned)"; offset 12 "Current offset"; }; datatype sitbpl1 msbfirst(32) "siTD buffer page pointer list page 1" { p 20 "Buffer pointer (4k aligned)"; _ 7 mbz; tp 2 type(xpos) "Transaction position"; tc 3 "Transaction count"; }; // 3.4.5 datatype sitblp msbfirst(32) "siTD back link pointer" { bp 27 "Back pointer"; _ 4 mbz; t 1 "Terminate (0 -> bp is valid)"; }; // 3.5 datatype qtd msbfirst(32) "Queue element transfer descriptor" { next 32 type(lp) "Next element"; altnext 32 type(lp) "Alternate next pointer"; token 32 type(qttok) "Token"; bp0 32 type(qtbp0) "Buffer pointer 0"; bp1 32 type(qtbp1) "Buffer pointer 1"; bp2 32 type(qtbp1) "Buffer pointer 2"; bp3 32 type(qtbp1) "Buffer pointer 3"; bp4 32 type(qtbp1) "Buffer pointer 4"; }; // 3.5.3 constants pid "PID token encoding" { pid_out = 0b00 "Generates OUT token (E1H)"; pid_in = 0b01 "Generates IN token (69H)"; pid_setup = 0b10 "Generates SETUP token (2DH)"; pid_rsvd = 0b11 "Reserved"; }; datatype qttok msbfirst(32) "qTD Token" { toggle 1 "Data toggle"; tbt 15 "Total bytes to transfer"; ioc 1 "Interrupt on complete"; cp 3 "Current page"; cerr 2 "Error counter"; pidc 2 type(pid) "PID code token"; active 1 "Status active"; halted 1 "Serious error at endpoint"; dbe 1 "Data buffer error"; babble 1 "Babble detected"; xacterr 1 "Transaction error"; mmf 1 "Missed micro-frame"; sts 1 "Split transaction state"; ping 1 "Ping state"; }; // 3.5.4 datatype qtbp0 msbfirst(32) "Queue element buffer pointer page 0" { p 20 "Buffer pointer (4k aligned)"; offset 12 "Current offset"; }; datatype qtbp1 msbfirst(32) "Queue element buffer pointer page 1" { p 20 "Buffer pointer (4k aligned)"; _ 12 mbz; }; // 3.6 datatype qh msbfirst(32) "Queue head" { hlp 32 type(lp) "Horizontal link pointer"; cap1 32 type(qhcap1) "Endpoint capabilities/characteristics 1"; cap2 32 type(qhcap2) "Endpoint capabilities/characteristics 2"; current 32 type(lp) "Current element"; next 32 type(lp) "Next element"; altnext 32 type(qhlp) "Alternate next pointer"; token 32 type(qttok) "Token"; bp0 32 type(qtbp0) "Buffer pointer 0"; bp1 32 type(qhbp1) "Buffer pointer 1"; bp2 32 type(qhbp2) "Buffer pointer 2"; bp3 32 type(qtbp1) "Buffer pointer 3"; bp4 32 type(qtbp1) "Buffer pointer 4"; }; // 3.6.2 constants speed width(2) "Endpoint speed" { fullspeed = 0b00 "Full-speed (12Mbs)"; lowspeed = 0b01 "Low-speed (1.5Mbs)"; highspeed = 0b10 "High-speed (480 Mb/s)"; }; datatype qhcap1 msbfirst(32) "Endpoint capabilities: queue head word 1"{ rl 4 "NAK count reload"; c 1 "Control endpoint flag"; mpl 11 "Maximum packet length"; h 1 "Head of reclamation list flag"; dtc 1 "Data toggle control"; eps 2 type(speed) "Endpoint speed"; epn 4 "Endpoint number"; i 1 "Inactivate on next transaction"; da 7 "Device address"; }; datatype qhcap2 msbfirst(32) "Endpoint capabilities: queue head word 2"{ mult 2 "High-bandwidth pipe multiplier"; port 7 "Port number"; hub 7 "Hub address"; scm 8 "Split completion mask"; ism 8 "Interrupt schedule mask"; }; // 3.6.3 datatype qhlpa msbfirst(32) "Alternate queue head link pointer" { p 27 "Frame list link pointer"; nakcnt 4 "NACK counter"; t 1 "Pointer value invalid"; }; datatype qhbp1 msbfirst(32) "Queue head buffer pointer page 1" { p 20 "Buffer pointer (4k aligned)"; _ 4 mbz; cpm 8 "Split-transaction complete-split progress"; }; datatype qhbp2 msbfirst(32) "Queue head buffer pointer page 2" { p 20 "Buffer pointer (4k aligned)"; sb 7 "S-bytes"; ft 5 "Split-transaction frame tag"; }; // 3.7 datatype fstm msbfirst(32) "Periodic Frame Span Traversal Node" { normal 32 type(lp) "Normal path link pointer"; back 32 type(lp) "Back path link pointer"; };*/ };