1/** 2 * \brief This file contains code to initalize the EHCI controller and to 3 * handle the interrupts 4 */ 5 6/* 7 * Copyright (c) 2007-2013 ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdlib.h> 16#include <stdio.h> 17#include <string.h> 18#include <barrelfish/barrelfish.h> 19 20#include <usb/usb.h> 21 22#include <usb_controller.h> 23#include <usb_device.h> 24 25#include "usb_ehci.h" 26#include "usb_ehci_memory.h" 27#include "usb_ehci_bus.h" 28#include "usb_ehci_root_hub.h" 29#include "usb_ehci_xfer.h" 30 31/** 32 * \brief performs a soft reset on the EHCI host controller 33 * 34 * \param hc the ehci controller to reset 35 */ 36usb_error_t usb_ehci_hc_reset(usb_ehci_hc_t *hc) 37{ 38 /* write the reset bit */ 39 ehci_usbcmd_hcr_wrf(&hc->ehci_base, 1); 40 41 /* wait some time to let rest complete */ 42 lib_usb_wait(200); 43 44 for (uint8_t i = 0; i < 10; i++) { 45 if (ehci_usbcmd_hcr_rdf(&hc->ehci_base)) { 46 /* 47 * the host controller sets this bit to 0 if the rest is complete 48 * therefore we have to wait some more time 49 */ 50 lib_usb_wait(200); 51 continue; 52 } 53 } 54 55 /* last check if reset was completed */ 56 if (ehci_usbcmd_hcr_rdf(&hc->ehci_base)) { 57 return (USB_ERR_TIMEOUT); 58 } 59 60 usb_error_t err = USB_ERR_OK; 61 62 /* 63 * The EHCI specification says that certain registers must have a 64 * defined value after reset while others are undefined. 65 * 66 * The following code checks if the reset was successful. 67 */ 68 if ((ehci_usbcmd_rawrd(&hc->ehci_base) & 0xFFFFF0FF) != 0x00080000) { 69 debug_printf("WARNING: USBCMD has wrong value.\n"); 70 err = USB_ERR_IOERROR; 71 } 72 if (ehci_usbsts_rawrd(&hc->ehci_base) != 0x00001000) { 73 debug_printf("WARNING: USBST has wrong value.\n"); 74 err = USB_ERR_IOERROR; 75 } 76 if (ehci_usbintr_rawrd(&hc->ehci_base) != 0x00000000) { 77 debug_printf("WARNING: USBINTR has wrong value.\n"); 78 err = USB_ERR_IOERROR; 79 } 80 if (ehci_frindex_rawrd(&hc->ehci_base) != 0x00000000) { 81 debug_printf("WARNING:FRINDEX has wrong value.\n"); 82 err = USB_ERR_IOERROR; 83 } 84 if (ehci_ctrldssegment_rawrd(&hc->ehci_base) != 0x00000000) { 85 debug_printf("WARNING: Reset is succeeded: CTRLDS has wrong value.\n"); 86 err = USB_ERR_IOERROR; 87 } 88 if (ehci_configflag_rawrd(&hc->ehci_base) != 0x00000000) { 89 debug_printf("WARNING: CONFIGFLG has wrong value.\n"); 90 err = USB_ERR_IOERROR; 91 } 92 if ((ehci_portsc_rawrd(&hc->ehci_base, 0) | 0x00001000) != 0x00003000) { 93 debug_printf("WARNING: PORTSC has wrong value.\n"); 94 err = USB_ERR_IOERROR; 95 } 96 97 return (err); 98} 99 100/** 101 * \brief halts the EHCI controller. Running transactions are finished first 102 * 103 * \param hc the host controller to halt 104 */ 105static usb_error_t usb_ehci_hc_halt(usb_ehci_hc_t *hc) 106{ 107 /* write the reset bit */ 108 ehci_usbcmd_wr(&hc->ehci_base, 0x0); 109 110 /* 111 * Wait some time before start checking 112 */ 113 lib_usb_wait(200); 114 115 /* wait until the reset is done */ 116 for (uint8_t i = 0; i < 10; i++) { 117 if (ehci_usbsts_hch_rdf(&hc->ehci_base)) { 118 /* all activity halted, return */ 119 return (USB_ERR_OK); 120 } 121 lib_usb_wait(200); 122 } 123 124 /* check if halted */ 125 if (ehci_usbsts_hch_rdf(&hc->ehci_base)) { 126 /* all activity halted, return */ 127 return (USB_ERR_OK); 128 } 129 130 return (USB_ERR_TIMEOUT); 131} 132 133usb_error_t usb_ehci_initialize_controller(usb_ehci_hc_t *hc) 134{ 135 /* 136 * XXX: 64 bit data structures are not supported at the moment 137 */ 138 if (ehci_hccparams_bit64ac_rdf(&hc->ehci_base)) { 139 debug_printf("NYI: Host controller uses 64-bit memory addresses!\n"); 140 return (USB_ERR_BAD_CONTEXT); 141 142 ehci_ctrldssegment_wr(&hc->ehci_base, 0); 143 } 144 145 /* 146 * STEP 1: Setting the start addresses of the periodic and asynchronous 147 * transfer lists 148 */ 149 ehci_periodiclistbase_wr(&hc->ehci_base, hc->pframes_phys); 150 ehci_asynclistaddr_wr(&hc->ehci_base, hc->qh_async_last->qh_self); 151 152 /* 153 * STEP 2: Setting the USBCMD register 154 */ 155 ehci_usbcmd_t cmd = 0; 156 // interrupt threshold to 1 micro frame 157 cmd = ehci_usbcmd_itc_insert(cmd, 1); 158 // enable the async schedule 159 cmd = ehci_usbcmd_ase_insert(cmd, 1); 160 // enable the periodic schedule 161 cmd = ehci_usbcmd_pse_insert(cmd, 1); 162 // keep the frame list size 163 cmd = ehci_usbcmd_fls_insert(cmd, ehci_usbcmd_fls_rdf(&hc->ehci_base)); 164 // start the host controller 165 cmd = ehci_usbcmd_rs_insert(cmd, 1); 166 167 // write the cmd value to the register 168 ehci_usbcmd_wr(&hc->ehci_base, cmd); 169 170 /* 171 * STEP 3: Take over the port ownership 172 */ 173 ehci_configflag_cf_wrf(&hc->ehci_base, 1); 174 175 /* wait till the HC is up and running */ 176 lib_usb_wait(200); 177 for (uint32_t i = 0; i < 10; i++) { 178 if (!ehci_usbsts_hch_rdf(&hc->ehci_base)) { 179 break; 180 } 181 lib_usb_wait(200); 182 } 183 184 185 if (ehci_usbsts_hch_rdf(&hc->ehci_base)) { 186 /* the host controller is still not started. */ 187 return (USB_ERR_TIMEOUT); 188 } 189 190 /* 191 * STEP 4: Enable the interrupts 192 */ 193 ehci_usbintr_wr(&hc->ehci_base, hc->enabled_interrupts); 194 195 /* 196 * STEP 5: Check if everything is fine i.e. controller running. 197 */ 198 if (ehci_usbsts_hch_rdf(&hc->ehci_base)) { 199 /* 200 * the HC does not want to do what we want 201 */ 202 debug_printf("ERROR: Host controller does not start...\n"); 203 204 return (USB_ERR_IOERROR); 205 } 206 207 /* 208 * STEP 4: Enable power on the ports. 209 * 210 * R/W���Host controller has port power control switches. This bit 211 * represents the current setting of the switch (0 = off, 1 = on). When 212 * power is not available on a port (i.e. PP equals a 0), the port is non- 213 * functional and will not report attaches, detaches, etc. 214 */ 215 if (ehci_hcsparams_ppc_rdf(&hc->ehci_base)) { 216 for (uint8_t i = 0; i < hc->rh_num_ports; i++) { 217 ehci_portsc_pp_wrf(&hc->ehci_base, i, 1); 218 } 219 } 220 221 debug_printf("EHCI controller up and running.\n"); 222 223 return (USB_ERR_OK); 224} 225 226 227/** 228 * \brief Interrupt handler for the EHCI controller hardware 229 * 230 * \param hc host controller 231 */ 232void usb_ehci_interrupt(usb_host_controller_t *host) 233{ 234 USB_DEBUG_TR_ENTER; 235 236 usb_ehci_hc_t *hc = (usb_ehci_hc_t *) host->hc_control; 237 238 /* 239 * read the status register and mask out the interrupts [5..0] 240 */ 241 ehci_usbsts_t intr = ehci_usbsts_rawrd(&hc->ehci_base) & 0x3F; 242 243 if (!(intr)) { 244 /* there was no interrupt for this controller */ 245 return; 246 } 247 248 if (!(intr & hc->enabled_interrupts)) { 249 /* there was an interrupt we dont have enabled */ 250 USB_DEBUG("Unenabled interrupt happened.\n"); 251 return; 252 } 253 254 /* acknowledge the interrupts */ 255 ehci_usbsts_wr(&hc->ehci_base, intr); 256 257 intr &= hc->enabled_interrupts; 258 259 if (ehci_usbsts_hse_extract(intr)) { 260 /* 261 * host system error -> unrecoverable error 262 * serious error occurs during a host system access involving the host 263 * controller module. 264 */ 265 USB_DEBUG("EHCI controller encountered an unrecoverable error\n"); 266 USER_PANIC("NYI: handling of unrecoverable errors! \n"); 267 268 } 269 270 uint8_t pcd_disabled = 0; 271 272 if (ehci_usbsts_pcd_extract(intr)) { 273 /* 274 * port change detected 275 * there is something going on on the port e.g. a new device is attached 276 * 277 * This interrupt stays enabled until the port is reset, so to avoid 278 * multiple interrupts, disable the port change interrupts for now. 279 */ 280 ehci_usbsts_pcd_insert(hc->enabled_interrupts, 0); 281 282 /* disable the PCD interrupt for now */ 283 ehci_usbintr_pcie_wrf(&hc->ehci_base, 0); 284 285 pcd_disabled = 1; 286 287 /* handle port status change */ 288 usb_ehci_roothub_interrupt(hc); 289 } 290 291 intr = ehci_usbsts_pcd_insert(intr, 0); 292 intr = ehci_usbsts_iaa_insert(intr, 0); 293 intr = ehci_usbsts_usbei_insert(intr, 0); 294 intr = ehci_usbsts_usbi_insert(intr, 0); 295 296 if (intr != 0) { 297 USB_DEBUG("NOTICE: Blocking interrupt %"PRIx32"\n", intr); 298 /* 299 * there is still an interrupt left, so block on this type 300 */ 301 hc->enabled_interrupts &= ~intr; 302 ehci_usbintr_wr(&hc->ehci_base, hc->enabled_interrupts); 303 } 304 305 /* poll the USB transfers */ 306 usb_ehci_poll(hc); 307 308 if (pcd_disabled) { 309 /* enable the port status change interrupt again */ 310 ehci_usbintr_pcie_insert(hc->enabled_interrupts, 1); 311 ehci_usbintr_pcie_wrf(&hc->ehci_base, 1); 312 } 313 314 USB_DEBUG_TR_RETURN; 315} 316 317/** 318 * \brief initializes the ehci host controller and creates the queues 319 * 320 * \param hc the ehci controller to initialize 321 * \param base the base address of the ehci controller 322 */ 323usb_error_t usb_ehci_init(usb_ehci_hc_t *hc, uintptr_t base) 324{ 325 /* 326 * STEP 1: Mackerel init 327 * Initialization of the ehci_t struct has to be done in two steps 328 * since the ehci has capability registers and operational registers 329 * which offsets has to be read out of the caplength register first. 330 */ 331 ehci_initialize(&hc->ehci_base, (mackerel_addr_t) base, NULL); 332 333 /* getting the operational register offset */ 334 uint8_t cap_offset = ehci_caplength_rd(&hc->ehci_base); 335 336 if (cap_offset == 0) { 337 debug_printf("ERROR: EHCI capability register length is zero.\n"); 338 return (USB_ERR_INVAL); 339 } 340 341 ehci_initialize(&hc->ehci_base, (mackerel_addr_t) base, 342 (mackerel_addr_t) (base + cap_offset)); 343 344 /* 345 * STEP 2: getting the number of ports and the revision 346 */ 347 hc->ehci_revision = ehci_hciversion_rd(&hc->ehci_base); 348 hc->rh_num_ports = ehci_hcsparams_n_ports_rdf(&hc->ehci_base); 349 350 debug_printf("Device found: EHCI controller rev: %x.%x with %u ports\n", 351 hc->ehci_revision >> 8, hc->ehci_revision & 0xFF, hc->rh_num_ports); 352 353 /* 354 * STEP 3: perform halt 355 * This stops the execution of (potentially) existing transfers 356 */ 357 usb_error_t err; 358 err = usb_ehci_hc_halt(hc); 359 if (err != USB_ERR_OK) { 360 debug_printf("WARNING: Host controller has not halted properly.\n"); 361 } 362 363 /* 364 * STEP 4: perform host controller reset 365 * Performing a reset also checks the register fields for the correct values 366 */ 367 err = usb_ehci_hc_reset(hc); 368 if (err != USB_ERR_OK) { 369 debug_printf("ERROR: Host controller not reset properly. \n"); 370 } 371 372 /* after reset this field should have been initialized to a valid value */ 373 if (ehci_usbcmd_fls_rdf(&hc->ehci_base) == ehci_frame_rsvd) { 374 /* 375 * this field should be initialized to a correct values 376 * having FLS=0x3 is invalid! 377 */ 378 debug_printf("ERROR: Wrong frame length size\n"); 379 return (USB_ERR_IOERROR); 380 } 381 382 /* 383 * STEP 5: init the generic host controller 384 * This fills out the missing fields of the generic host controller 385 */ 386 hc->controller->hcdi_bus_fn = usb_ehci_get_bus_fn(); 387 hc->controller->usb_revision = USB_REV_2_0; 388 hc->controller->devices = hc->devices; 389 hc->controller->devices_max = USB_EHCI_MAX_DEVICES; 390 391 /* 392 * STEP 6: Setting up the enabled interrupts 393 * this does not activate them, just prepare it for later. 394 */ 395 ehci_usbintr_t en_intrs = 0; 396 en_intrs = ehci_usbintr_iaae_insert(en_intrs, 0); 397 en_intrs = ehci_usbintr_hsee_insert(en_intrs, 1); 398 en_intrs = ehci_usbintr_pcie_insert(en_intrs, 1); 399 en_intrs = ehci_usbintr_usbie_insert(en_intrs, 1); 400 en_intrs = ehci_usbintr_usbeie_insert(en_intrs, 1); 401 hc->enabled_interrupts = en_intrs; 402 403 /* 404 * STEP 7: Setting up the initial transfer queues 405 */ 406 usb_ehci_qh_t *qh; 407 408 /* setup the terminate qheue head */ 409 qh = usb_ehci_qh_alloc(); 410 qh->qh_next_qtd = USB_EHCI_LINK_TERMINATE; 411 qh->qh_alt_next_qtd = USB_EHCI_LINK_TERMINATE; 412 qh->qh_status.status = USB_EHCI_QTD_STATUS_HALTED; 413 hc->qh_terminate = qh; 414 415 /* 416 * STEP 7.1a: Initialize the interrupt transfer queues 417 */ 418 for (uint32_t i = 0; i < USB_EHCI_VFRAMELIST_COUNT; i++) { 419 qh = usb_ehci_qh_alloc(); 420 421 hc->qh_intr_last[i] = qh; 422 qh->qh_ep.ep_speed = USB_EHCI_QH_SPEED_HIGH; 423 qh->qh_ep.mult = 1; 424 qh->qh_curr_qtd = 0; 425 qh->qh_next_qtd = USB_EHCI_LINK_TERMINATE; 426 qh->qh_alt_next_qtd = USB_EHCI_LINK_TERMINATE; 427 qh->qh_status.status = USB_EHCI_QTD_STATUS_HALTED; 428 qh->qh_self |= USB_EHCI_LINKTYPE_QH; 429 } 430 431 /* 432 * STEP 7.1b: Link the queue heads together that they form the 2ms 433 * polling interval 434 */ 435 uint16_t bit = USB_EHCI_VFRAMELIST_COUNT / 2; 436 uint32_t curr, next; 437 438 while (bit) { 439 curr = bit; 440 while (curr & bit) { 441 usb_ehci_qh_t *qh_curr; 442 usb_ehci_qh_t *qh_next; 443 444 next = (curr ^ bit) | (bit / 2); 445 446 qh_curr = hc->qh_intr_last[curr]; 447 qh_next = hc->qh_intr_last[next]; 448 449 qh_curr->qh_link = qh_next->qh_self; 450 451 curr++; 452 } 453 bit >>= 1; 454 } 455 456 qh = hc->qh_intr_last[0]; 457 qh->qh_link = USB_EHCI_LINK_TERMINATE; 458 459 /* 460 * STEP 7.2: Initialize the isochronus split transaction queues together 461 * with the isochronus transaction queues 462 */ 463 464 usb_ehci_sitd_t *sitd; 465 usb_ehci_itd_t *itd; 466 467 for (uint32_t i = 0; i < USB_EHCI_VFRAMELIST_COUNT; i++) { 468 469 sitd = usb_ehci_sitd_alloc(); 470 hc->qh_sitd_fs_last[i] = sitd; 471 472 sitd->sitd_self |= USB_EHCI_LINKTYPE_SITD; 473 474 sitd->sitd_back_link = USB_EHCI_LINK_TERMINATE; 475 476 next = i | (USB_EHCI_VFRAMELIST_COUNT / 2); 477 sitd->sitd_next = hc->qh_intr_last[next]->qh_self; 478 479 itd = usb_ehci_itd_alloc(); 480 hc->qh_itd_hs_last[i] = itd; 481 482 itd->itd_self |= USB_EHCI_LINKTYPE_ITD; 483 484 itd->itd_next = sitd->sitd_self; 485 } 486 487 /* 488 * STEP 8: Initialize the physical frames for the periodic transfers 489 * and store the periodic frame list iTDs addresses 490 */ 491 if (hc->pframes == NULL) { 492 usb_ehci_pframes_alloc(hc); 493 } 494 495 assert(hc->pframes); 496 497 usb_paddr_t *pframes = (hc->pframes); 498 499 for (uint32_t i = 0; i < USB_EHCI_FRAMELIST_COUNT; i++) { 500 next = i & (USB_EHCI_VFRAMELIST_COUNT - 1); 501 (pframes[i]) = hc->qh_itd_hs_last[next]->itd_self; 502 } 503 504 /* 505 * STEP 9: Initialize the asynchronous transfer queue 506 */ 507 qh = usb_ehci_qh_alloc(); 508 509 hc->qh_async_last = qh; 510 hc->qh_async_first = qh; 511 512 qh->qh_ep.ep_speed = USB_EHCI_QH_SPEED_HIGH; 513 qh->qh_ep.head_reclamation = 1; 514 qh->qh_ep.mult = 1; 515 qh->qh_link = qh->qh_self | USB_EHCI_LINKTYPE_QH | USB_EHCI_LINK_TERMINATE; 516 qh->qh_alt_next_qtd = USB_EHCI_LINK_TERMINATE; 517 qh->qh_next_qtd = USB_EHCI_LINK_TERMINATE; 518 qh->qh_status.status = USB_EHCI_QTD_STATUS_HALTED; 519 520 /* 521 * STEP 10: Allocate the root hub device 522 */ 523 struct usb_device *root_hub = usb_device_alloc(hc->controller, NULL, 0, 0, 524 1, USB_SPEED_HIGH, USB_MODE_HOST); 525 526 if (root_hub) { 527 usb_hub_init(root_hub); 528 hc->rh_device = root_hub; 529 hc->controller->root_hub = root_hub; 530 } else { 531 USER_PANIC("ERROR: No root hub present!"); 532 } 533 534 hc->devices[USB_ROOTHUB_ADDRESS] = root_hub; 535 536 /* 537 * STEP 11: Call the register initialization function 538 */ 539 err = usb_ehci_initialize_controller(hc); 540 541 /* 542 * STEP 12: do an initial poll, since the interrupts may be risen before 543 * we started the interrupt handler 544 */ 545 if (err == USB_ERR_OK) { 546 usb_ehci_poll(hc); 547 } 548 549 return (err); 550} 551