1/* 2 * Copyright (c) 2012, ETH Zurich. All rights reserved. 3 * 4 * This file is distributed under the terms in the attached LICENSE file. 5 * If you do not find this file, copies can be found by writing to: 6 * ETH Zurich D-INFK, Universitaestr. 6, CH-8092 Zurich. Attn: Systems Group. 7 */ 8 9/* 10 * ohci.dev 11 * 12 * DESCRIPTION: Open Host Controller Interface (OHCI) description 13 * 14 * Archaic USB interface, but still found on e.g. ATI and NVidia 15 * chipsets. 16 * 17 * Numbers in comments refer to the OpenHCI Open Host Controller 18 * Interface Specification for USB, by Compaq, Microsoft, and National 19 * Semiconductor, 09/14/99 2:33 PM, Release: 1.0a 20 */ 21 22 23device ohci lsbfirst ( io base ) "OHCI USB controller" { 24 25/* 26 // 27 // Data structures 28 // 29 30 // 4.2.1 31 constants direction width(2) "Data flow direction" { 32 dir_td = 0b00 "Get direction from TD"; 33 dir_out = 0b01 "Out"; 34 dir_in = 0b10 "In"; 35 dir_td1 = 0b11 "Get direction from TD (alt)"; 36 }; 37 38 datatype epdesc lsbfirst(32) "Endpoint descriptor" { 39 fa 7 "Function address"; 40 en 4 "Endpoint number"; 41 d 2 type(direction) "Direction"; 42 s 1 "Speed (1=low, 0=full)"; 43 k 1 "Skip"; 44 f 1 "Format (1=isochronous, 0=general)"; 45 mps 11 "Maximum packet size"; 46 _ 5; 47 _ 4; 48 tailp 28 "TD queue tail pointer"; 49 h 1 "Halted"; 50 c 1 "Toggle carry"; 51 _ 2 mbz; 52 headp 28 "TD queue head pointer"; 53 _ 4; 54 nexted 28 "Next endpoint descriptor"; 55 }; 56 57 // 4.3.1 58 constants pid width(2) "Direction / PID for token" { 59 pid_setup = 0b00 "Setup (to endpoint)"; 60 pid_out = 0b01 "To endpoint"; 61 pid_in = 0b10 "From endpoint"; 62 }; 63 datatype gentd lsbfirst(32) "General transfer descriptor" { 64 _ 18; 65 r 1 "Buffer rounding"; 66 dp 2 type(pid) "Direction or PID"; 67 di 3 "Delay interrupt frames"; 68 t 2 "Data toggle"; 69 ec 2 "Error count"; 70 cc 4 type(ccode) "Condition code for last attempted transaction"; 71 cbp 32 "Current buffer pointer"; 72 _ 4 mbz; 73 nexttd 28 "Next transfer descriptor"; 74 be 32 "Buffer end"; 75 }; 76 77 78 // 4.3.2 79 datatype isotd lsbfirst(32) "Isochronous transfer descriptor" { 80 sf 16 "Starting frame"; 81 _ 5; 82 di 3 "Delay interrupt frames"; 83 fc 3 "Frame count"; 84 _ 1; 85 cc 4 type(ccode) "Condition code for last attempted transaction"; 86 _ 12; 87 bp0 20 "Buffer page 0"; 88 _ 5 mbz; 89 nexttd 27 "Next transfer descriptor"; 90 be 32 "Buffer end"; 91 ofpsw0 16 "Offset / packet status word 0"; 92 ofpsw1 16 "Offset / packet status word 1"; 93 ofpsw2 16 "Offset / packet status word 2"; 94 ofpsw3 16 "Offset / packet status word 4"; 95 ofpsw4 16 "Offset / packet status word 3"; 96 ofpsw5 16 "Offset / packet status word 5"; 97 ofpsw6 16 "Offset / packet status word 6"; 98 ofpsw7 16 "Offset / packet status word 7"; 99 }; 100 datatype psw lsbfirst(16) "Packet status word" { 101 size 11 "Size of packet"; 102 _ 1 mbz; 103 cc 4 type(ccode) "Condition code"; 104 }; 105 106 /// 4.3.3 107 constants ccode width(4) "Completion codes" { 108 cc_ne = 0b0000 "No error"; 109 cc_crc = 0b0001 "CRC error"; 110 cc_bs = 0b0010 "Bitstuffing violation"; 111 cc_dtm = 0b0011 "Data toggle PID mismatch"; 112 cc_stl = 0b0100 "EP returned stall PID"; 113 cc_dnr = 0b0101 "Device not responding"; 114 cc_pcf = 0b0110 "PID check failure"; 115 cc_uxp = 0b0111 "Unexpected PID"; 116 cc_dor = 0b1000 "Data overrun"; 117 cc_dur = 0b1001 "Data underrun"; 118 cc_bor = 0b1100 "Buffer overrun"; 119 cc_bur = 0b1101 "Buffer underrun"; 120 cc_nac = 0b1110 "Not accessed"; 121 cc_nac_ = 0b1111 "Not accessed (alternate)"; 122 }; 123*/ 124 // 125 // Registers 126 // 127 // 7.1 Control and status partition 128 // 129 130 // 7.1.1 Interface revision 131 /// Initially 0x10. 132 register revision ro io(base, 0x00) "Revision" { 133 rev 8 "BCD rep. of interface version"; 134 _ 24; 135 }; 136 137 // 7.1.2 Control register 138 constants state "Functional state" { 139 st_reset = 0b00 "Reset (after h/w reset)"; 140 st_resume = 0b01 "Resume from downstream port"; 141 st_operational = 0b10 "Operational (running)"; 142 st_suspend = 0b11 "Suspend (after s/w reset)"; 143 }; 144 // Initially 0x00 145 register control rw io(base, 0x04) "Control" { 146 cbsr 2 "Control/bulk service ratio"; 147 pe 1 "Periodic list enable"; 148 ie 1 "Isochronous enable"; 149 cle 1 "Control list enable"; 150 ble 1 "Bulk list enable"; 151 hcfs 2 type(state) "Host controller functional state"; 152 ir 1 "Interrupt routing"; 153 rwc 1 "Remote wakeup connected"; 154 rwe 1 "Remote wakeup enabled"; 155 _ 21; 156 }; 157 158 159 // 7.1.3 Command and Status 160 // Initially 0x00 161 register cmdstatus rw io(base, 0x08) "08 CommandStatus" { 162 hcr 1 "Host controller reset"; 163 clf 1 "Control list filled"; 164 blf 1 "Bulk list filled"; 165 ocr 1 "Ownership change request"; 166 _ 12; 167 soc 2 ro "Scheduling overrun count"; 168 _ 14; 169 }; 170 171 // 7.1.4-6: Interrupt registers 172 regtype interrupt "Interrupts" { 173 so 1 "Scheduling overrun"; 174 wdh 1 "Writeback done head"; 175 sf 1 "Start of frame"; 176 rd 1 "Resume detected"; 177 ue 1 "Unrecoverable error"; 178 fno 1 "Frame number overflow"; 179 rhsc 1 "Root hub status change"; 180 _ 23; 181 oc 1 "Ownership change"; 182 mie 1 "Master interrupt enable"; 183 }; 184 register intstatus rw io(base, 0x0C) "Interrupt status" 185 type(interrupt); 186 register intenable rw io(base, 0x10) "Interrupt enable" 187 type(interrupt); 188 register intdisable rw io(base, 0x14) "Interrupt disable" 189 type(interrupt); 190 191 // 192 // 7.2 Memory pointer partition 193 // 194 195 // 7.2.1 196 register hcca rw io(base, 0x18) "Host controller communication area" { 197 _ 8 mbz; 198 hcca 24 "Physical address"; 199 }; 200 201 regtype physptr "Physical address pointer" { 202 _ 4 mbz; 203 addr 28 "Address"; 204 }; 205 206 // 7.2.2. 207 register period_cur ro io(base, 0x1C) "Cur. isochronous or int. ED" 208 type(physptr); 209 210 // 7.2.3 211 register ctrl_head rw io(base, 0x20) "First ED of control list" 212 type(physptr); 213 214 215 // 7.2.4 216 register ctrl_cur rw io(base, 0x24) "Current ED of control list" 217 type(physptr); 218 219 // 7.2.5 220 register bulk_head rw io(base, 0x28) "First ED of bulk list" 221 type(physptr); 222 223 // 7.2.6 224 register bulk_cur rw io(base, 0x2C) "Current ED of bulk list" 225 type(physptr); 226 227 228 // 7.2.7 229 register done_head ro io(base, 0x30) "Done head pointer" 230 type(physptr); 231 232 // 233 // 7.3 Frame counter partition 234 // 235 236 // 7.3.1 237 register fm_interval rw io(base, 0x34) "Frame interval" { 238 fi 14 "Frame interval (dflt 0x2edf)"; 239 _ 2; 240 fsmps 15 "FS largest data packet"; 241 fit 1 "Frame interval toggle"; 242 }; 243 244 // 7.3.2 245 register fm_remain ro io(base, 0x38) "Frame remaining" { 246 fr 14 "Bit time remaining in current frame"; 247 _ 17; 248 frt 1 "Frame remaining toggle"; 249 }; 250 251 // 7.3.3 252 register fm_num ro io(base, 0x3C) "Frame number" { 253 fn 16 "Frame number (16-bit counter)"; 254 _ 16; 255 }; 256 257 // 7.3.4 258 register period_start rw io(base, 0x40) "Period start" { 259 ps 14 "Start time for processing periodic list"; 260 _ 18; 261 }; 262 263 // 7.3.5 264 register hclsthreshold rw io(base, 0x44) "LS threshold" { 265 lst 11 "Low-speed threshold (should be 0x0628)"; 266 _ 21; 267 }; 268 269 // 270 // 7.4 Root Hub partition 271 // 272 273 // 7.4.1 274 register rh_descra rw io(base, 0x48) "Root hub descriptor a" { 275 ndp 8 ro "Number of downstream ports"; 276 psm 1 "Power switching mode"; 277 nps 1 "No power switching"; 278 dt 1 ro "Device type"; 279 ocpm 1 "Overcurrent protection mode"; 280 nocp 1 "No overcurrent protection"; 281 _ 11; 282 potpgt 8 "Power-on to power-good time (* 2ms)"; 283 }; 284 285 // 7.4.2 286 register rh_descrb rw io(base, 0x4C) "Root hub descriptor b" { 287 dr 16 "Device removal"; 288 ppcm 16 "Port power control mask"; 289 }; 290 291 // 7.4.3 292 register rh_status rw io(base, 0x50) "Root hub status" { 293 lps 1 wo "Clear global power"; 294 oci 1 ro "Overcurrent indicator"; 295 _ 13; 296 drwe 1 rw1c "Device remote wakeup enable"; 297 lpsc 1 wo "Set globl power"; 298 ocic 1 rw1c "Overcurrent indicator change"; 299 _ 13; 300 crwe 1 wo "Clear remote wakeup enable"; 301 }; 302 303 // 7.4.4 304 // Assume 256 ports at this stage; it's actually given by 305 // rh_descra->ndp. 306 regarray rh_portstat ro io(base, 0x54)[256] "Root hub port status" { 307 ccs 1 "Current connection status"; 308 pes 1 "Port enable status"; 309 pss 1 "Port suspend status"; 310 poci 1 "Port overcurrent indicator"; 311 prs 1 "Port reset status"; 312 _ 3; 313 pps 1 "Port power status"; 314 lsda 1 "Low-speed device attached"; 315 _ 6; 316 csc 1 "Connect status change"; 317 pesc 1 "Port enable status change"; 318 pssc 1 "Port suspend status change"; 319 ocic 1 "Port overcurrent indicator change"; 320 prsc 1 "Port reset status change"; 321 _ 11; 322 }; 323 regarray rh_portctrl wo also io(base, 0x54)[256] "Root hub port control" { 324 cpe 1 "Clear port enable"; 325 spe 1 "Set port enable"; 326 sps 1 "Set port suspend"; 327 css 1 "Clear suspend status"; 328 spr 1 "Set port reset"; 329 _ 3; 330 spp 1 "Set port power"; 331 cpp 1 "Clear port power"; 332 _ 6; 333 csc 1 "Clear connect status change"; 334 pesc 1 "Clear port enable status change"; 335 pssc 1 "Clear port suspend status change"; 336 ocic 1 "Clear port overcurrent indicator change"; 337 prsc 1 "Clear port reset status change"; 338 _ 11; 339 }; 340}; 341