Changeset ab5a0830 in mainline for uspace/drv/bus/usb/xhci/hc.c
- Timestamp:
- 2017-09-27T15:04:39Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 548c123
- Parents:
- 6da6039
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/hc.c
r6da6039 rab5a0830 44 44 #include "commands.h" 45 45 46 static const irq_cmd_t irq_commands[] = {47 {48 .cmd = CMD_PIO_READ_32,49 .dstarg = 1,50 .addr = NULL51 },52 {53 .cmd = CMD_AND,54 .srcarg = 1,55 .dstarg = 2,56 .value = 057 },58 {59 .cmd = CMD_PREDICATE,60 .srcarg = 2,61 .value = 262 },63 {64 .cmd = CMD_PIO_WRITE_A_32,65 .srcarg = 1,66 .addr = NULL67 },68 {69 .cmd = CMD_ACCEPT70 }71 };72 73 46 /** 74 47 * Default USB Speed ID mapping: Table 157 … … 240 213 } 241 214 215 /* 216 * Pseudocode: 217 * ip = read(intr[0].iman) 218 * if (ip) { 219 * status = read(usbsts) 220 * assert status 221 * assert ip 222 * accept (passing status) 223 * } 224 * decline 225 */ 226 static const irq_cmd_t irq_commands[] = { 227 { 228 .cmd = CMD_PIO_READ_32, 229 .dstarg = 3, 230 .addr = NULL /* intr[0].iman */ 231 }, 232 { 233 .cmd = CMD_AND, 234 .srcarg = 3, 235 .dstarg = 4, 236 .value = 0 /* host2xhci(32, 1) */ 237 }, 238 { 239 .cmd = CMD_PREDICATE, 240 .srcarg = 4, 241 .value = 5 242 }, 243 { 244 .cmd = CMD_PIO_READ_32, 245 .dstarg = 1, 246 .addr = NULL /* usbsts */ 247 }, 248 { 249 .cmd = CMD_AND, 250 .srcarg = 1, 251 .dstarg = 2, 252 .value = 0 /* host2xhci(32, XHCI_STATUS_ACK_MASK) */ 253 }, 254 { 255 .cmd = CMD_PIO_WRITE_A_32, 256 .srcarg = 2, 257 .addr = NULL /* usbsts */ 258 }, 259 { 260 .cmd = CMD_PIO_WRITE_A_32, 261 .srcarg = 4, 262 .addr = NULL /* intr[0].iman */ 263 }, 264 { 265 .cmd = CMD_ACCEPT 266 }, 267 { 268 .cmd = CMD_DECLINE 269 } 270 }; 271 242 272 243 273 /** … … 276 306 277 307 void *intr0_iman = RNGABSPTR(hc->mmio_range) + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_RTSOFF) + offsetof(xhci_rt_regs_t, ir[0]); 308 void *usbsts = RNGABSPTR(hc->mmio_range) + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_LENGTH) + offsetof(xhci_op_regs_t, usbsts); 278 309 code->cmds[0].addr = intr0_iman; 279 code->cmds[3].addr = intr0_iman;280 310 code->cmds[1].value = host2xhci(32, 1); 311 code->cmds[3].addr = usbsts; 312 code->cmds[4].value = host2xhci(32, XHCI_STATUS_ACK_MASK); 313 code->cmds[5].addr = usbsts; 314 code->cmds[6].addr = intr0_iman; 281 315 282 316 return hw_res->irqs.irqs[0]; … … 356 390 } 357 391 392 /** 393 * Used only when polling. Shall supplement the irq_commands. 394 */ 358 395 int hc_status(xhci_hc_t *hc, uint32_t *status) 359 396 { 360 *status = XHCI_REG_RD(hc->op_regs, XHCI_OP_STATUS); 361 XHCI_REG_WR(hc->op_regs, XHCI_OP_STATUS, *status & XHCI_STATUS_ACK_MASK); 362 363 usb_log_debug2("HC(%p): Read status: %x", hc, *status); 397 int ip = XHCI_REG_RD(hc->rt_regs->ir, XHCI_INTR_IP); 398 if (ip) { 399 *status = XHCI_REG_RD(hc->op_regs, XHCI_OP_STATUS); 400 XHCI_REG_WR(hc->op_regs, XHCI_OP_STATUS, *status & XHCI_STATUS_ACK_MASK); 401 XHCI_REG_WR(hc->rt_regs->ir, XHCI_INTR_IP, 1); 402 403 /* interrupt handler expects status from irq_commands, which is 404 * in xhci order. */ 405 *status = host2xhci(32, *status); 406 } 407 408 usb_log_debug2("HC(%p): Polled status: %x", hc, *status); 364 409 return EOK; 365 410 } … … 460 505 void hc_interrupt(xhci_hc_t *hc, uint32_t status) 461 506 { 462 /** 463 * TODO: This is a temporary workaround, when an event interrupt 464 * happens, status has the value of 3, which is equal to 465 * XHCI_REG_SHIFT(XHCI_OP_EINT), intstead to the correct 466 * XHCI_REG_MASK(XHCI_OP_EINT), which has the value of 8 (1 << 3). 467 * This is how e.g. FreeBSD does it. 468 */ 469 status = hc->op_regs->usbsts; 507 status = xhci2host(32, status); 470 508 471 509 /* TODO: Figure out how root hub interrupts work. */ … … 473 511 usb_log_debug2("Root hub interrupt."); 474 512 xhci_rh_interrupt(&hc->rh); 513 514 status &= ~XHCI_REG_MASK(XHCI_OP_PCD); 475 515 } 476 516 477 517 if (status & XHCI_REG_MASK(XHCI_OP_HSE)) { 478 518 usb_log_error("Host controller error occured. Bad things gonna happen..."); 519 status &= ~XHCI_REG_MASK(XHCI_OP_HSE); 479 520 } 480 521 481 522 if (status & XHCI_REG_MASK(XHCI_OP_EINT)) { 482 523 usb_log_debug2("Event interrupt."); 483 484 xhci_interrupter_regs_t *intr0 = &hc->rt_regs->ir[0]; 485 486 /** 487 * EINT has to be cleared before IP, but we also need to 488 * handle the event before clearing EINT. 489 */ 490 uint32_t ip = XHCI_REG_RD(intr0, XHCI_INTR_IP); 491 492 if (ip | 1) { // TODO: IP is being cleared right after it is set by the xHC. 493 hc_run_event_ring(hc, &hc->event_ring, intr0); 494 } 495 496 XHCI_REG_SET(hc->op_regs, XHCI_OP_EINT, 1); 497 498 if (ip) { 499 XHCI_REG_SET(intr0, XHCI_INTR_IP, 1); 500 } 501 } 502 503 if (status & XHCI_REG_MASK(XHCI_OP_PCD)) { 504 usb_log_error("Port change detected. Not implemented yet!"); 524 hc_run_event_ring(hc, &hc->event_ring, &hc->rt_regs->ir[0]); 525 status &= ~XHCI_REG_MASK(XHCI_OP_EINT); 505 526 } 506 527 507 528 if (status & XHCI_REG_MASK(XHCI_OP_SRE)) { 508 529 usb_log_error("Save/Restore error occured. WTF, S/R mechanism not implemented!"); 530 status &= ~XHCI_REG_MASK(XHCI_OP_SRE); 531 } 532 533 if (status) { 534 usb_log_error("Non-zero status after interrupt handling (%08x) - missing something?", status); 509 535 } 510 536 }
Note:
See TracChangeset
for help on using the changeset viewer.