|
|
1.1 ! root 1: /* ! 2: * QEMU USB OHCI Emulation ! 3: * Copyright (c) 2004 Gianni Tedesco ! 4: * Copyright (c) 2006 CodeSourcery ! 5: * Copyright (c) 2006 Openedhand Ltd. ! 6: * ! 7: * This library is free software; you can redistribute it and/or ! 8: * modify it under the terms of the GNU Lesser General Public ! 9: * License as published by the Free Software Foundation; either ! 10: * version 2 of the License, or (at your option) any later version. ! 11: * ! 12: * This library is distributed in the hope that it will be useful, ! 13: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 15: * Lesser General Public License for more details. ! 16: * ! 17: * You should have received a copy of the GNU Lesser General Public ! 18: * License along with this library; if not, see <http://www.gnu.org/licenses/>. ! 19: * ! 20: * TODO: ! 21: * o Isochronous transfers ! 22: * o Allocate bandwidth in frames properly ! 23: * o Disable timers when nothing needs to be done, or remove timer usage ! 24: * all together. ! 25: * o Handle unrecoverable errors properly ! 26: * o BIOS work to boot from USB storage ! 27: */ ! 28: ! 29: #include "hw/hw.h" ! 30: #include "qemu-timer.h" ! 31: #include "hw/usb.h" ! 32: #include "hw/pci.h" ! 33: #include "hw/sysbus.h" ! 34: #include "hw/qdev-addr.h" ! 35: ! 36: //#define DEBUG_OHCI ! 37: /* Dump packet contents. */ ! 38: //#define DEBUG_PACKET ! 39: //#define DEBUG_ISOCH ! 40: /* This causes frames to occur 1000x slower */ ! 41: //#define OHCI_TIME_WARP 1 ! 42: ! 43: #ifdef DEBUG_OHCI ! 44: #define DPRINTF printf ! 45: #else ! 46: #define DPRINTF(...) ! 47: #endif ! 48: ! 49: /* Number of Downstream Ports on the root hub. */ ! 50: ! 51: #define OHCI_MAX_PORTS 15 ! 52: ! 53: static int64_t usb_frame_time; ! 54: static int64_t usb_bit_time; ! 55: ! 56: typedef struct OHCIPort { ! 57: USBPort port; ! 58: uint32_t ctrl; ! 59: } OHCIPort; ! 60: ! 61: typedef struct { ! 62: USBBus bus; ! 63: qemu_irq irq; ! 64: MemoryRegion mem; ! 65: int num_ports; ! 66: const char *name; ! 67: ! 68: QEMUTimer *eof_timer; ! 69: int64_t sof_time; ! 70: ! 71: /* OHCI state */ ! 72: /* Control partition */ ! 73: uint32_t ctl, status; ! 74: uint32_t intr_status; ! 75: uint32_t intr; ! 76: ! 77: /* memory pointer partition */ ! 78: uint32_t hcca; ! 79: uint32_t ctrl_head, ctrl_cur; ! 80: uint32_t bulk_head, bulk_cur; ! 81: uint32_t per_cur; ! 82: uint32_t done; ! 83: int done_count; ! 84: ! 85: /* Frame counter partition */ ! 86: uint32_t fsmps:15; ! 87: uint32_t fit:1; ! 88: uint32_t fi:14; ! 89: uint32_t frt:1; ! 90: uint16_t frame_number; ! 91: uint16_t padding; ! 92: uint32_t pstart; ! 93: uint32_t lst; ! 94: ! 95: /* Root Hub partition */ ! 96: uint32_t rhdesc_a, rhdesc_b; ! 97: uint32_t rhstatus; ! 98: OHCIPort rhport[OHCI_MAX_PORTS]; ! 99: ! 100: /* PXA27x Non-OHCI events */ ! 101: uint32_t hstatus; ! 102: uint32_t hmask; ! 103: uint32_t hreset; ! 104: uint32_t htest; ! 105: ! 106: /* SM501 local memory offset */ ! 107: target_phys_addr_t localmem_base; ! 108: ! 109: /* Active packets. */ ! 110: uint32_t old_ctl; ! 111: USBPacket usb_packet; ! 112: uint8_t usb_buf[8192]; ! 113: uint32_t async_td; ! 114: int async_complete; ! 115: ! 116: } OHCIState; ! 117: ! 118: /* Host Controller Communications Area */ ! 119: struct ohci_hcca { ! 120: uint32_t intr[32]; ! 121: uint16_t frame, pad; ! 122: uint32_t done; ! 123: }; ! 124: #define HCCA_WRITEBACK_OFFSET offsetof(struct ohci_hcca, frame) ! 125: #define HCCA_WRITEBACK_SIZE 8 /* frame, pad, done */ ! 126: ! 127: #define ED_WBACK_OFFSET offsetof(struct ohci_ed, head) ! 128: #define ED_WBACK_SIZE 4 ! 129: ! 130: static void ohci_bus_stop(OHCIState *ohci); ! 131: static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev); ! 132: ! 133: /* Bitfields for the first word of an Endpoint Desciptor. */ ! 134: #define OHCI_ED_FA_SHIFT 0 ! 135: #define OHCI_ED_FA_MASK (0x7f<<OHCI_ED_FA_SHIFT) ! 136: #define OHCI_ED_EN_SHIFT 7 ! 137: #define OHCI_ED_EN_MASK (0xf<<OHCI_ED_EN_SHIFT) ! 138: #define OHCI_ED_D_SHIFT 11 ! 139: #define OHCI_ED_D_MASK (3<<OHCI_ED_D_SHIFT) ! 140: #define OHCI_ED_S (1<<13) ! 141: #define OHCI_ED_K (1<<14) ! 142: #define OHCI_ED_F (1<<15) ! 143: #define OHCI_ED_MPS_SHIFT 16 ! 144: #define OHCI_ED_MPS_MASK (0x7ff<<OHCI_ED_MPS_SHIFT) ! 145: ! 146: /* Flags in the head field of an Endpoint Desciptor. */ ! 147: #define OHCI_ED_H 1 ! 148: #define OHCI_ED_C 2 ! 149: ! 150: /* Bitfields for the first word of a Transfer Desciptor. */ ! 151: #define OHCI_TD_R (1<<18) ! 152: #define OHCI_TD_DP_SHIFT 19 ! 153: #define OHCI_TD_DP_MASK (3<<OHCI_TD_DP_SHIFT) ! 154: #define OHCI_TD_DI_SHIFT 21 ! 155: #define OHCI_TD_DI_MASK (7<<OHCI_TD_DI_SHIFT) ! 156: #define OHCI_TD_T0 (1<<24) ! 157: #define OHCI_TD_T1 (1<<25) ! 158: #define OHCI_TD_EC_SHIFT 26 ! 159: #define OHCI_TD_EC_MASK (3<<OHCI_TD_EC_SHIFT) ! 160: #define OHCI_TD_CC_SHIFT 28 ! 161: #define OHCI_TD_CC_MASK (0xf<<OHCI_TD_CC_SHIFT) ! 162: ! 163: /* Bitfields for the first word of an Isochronous Transfer Desciptor. */ ! 164: /* CC & DI - same as in the General Transfer Desciptor */ ! 165: #define OHCI_TD_SF_SHIFT 0 ! 166: #define OHCI_TD_SF_MASK (0xffff<<OHCI_TD_SF_SHIFT) ! 167: #define OHCI_TD_FC_SHIFT 24 ! 168: #define OHCI_TD_FC_MASK (7<<OHCI_TD_FC_SHIFT) ! 169: ! 170: /* Isochronous Transfer Desciptor - Offset / PacketStatusWord */ ! 171: #define OHCI_TD_PSW_CC_SHIFT 12 ! 172: #define OHCI_TD_PSW_CC_MASK (0xf<<OHCI_TD_PSW_CC_SHIFT) ! 173: #define OHCI_TD_PSW_SIZE_SHIFT 0 ! 174: #define OHCI_TD_PSW_SIZE_MASK (0xfff<<OHCI_TD_PSW_SIZE_SHIFT) ! 175: ! 176: #define OHCI_PAGE_MASK 0xfffff000 ! 177: #define OHCI_OFFSET_MASK 0xfff ! 178: ! 179: #define OHCI_DPTR_MASK 0xfffffff0 ! 180: ! 181: #define OHCI_BM(val, field) \ ! 182: (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT) ! 183: ! 184: #define OHCI_SET_BM(val, field, newval) do { \ ! 185: val &= ~OHCI_##field##_MASK; \ ! 186: val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \ ! 187: } while(0) ! 188: ! 189: /* endpoint descriptor */ ! 190: struct ohci_ed { ! 191: uint32_t flags; ! 192: uint32_t tail; ! 193: uint32_t head; ! 194: uint32_t next; ! 195: }; ! 196: ! 197: /* General transfer descriptor */ ! 198: struct ohci_td { ! 199: uint32_t flags; ! 200: uint32_t cbp; ! 201: uint32_t next; ! 202: uint32_t be; ! 203: }; ! 204: ! 205: /* Isochronous transfer descriptor */ ! 206: struct ohci_iso_td { ! 207: uint32_t flags; ! 208: uint32_t bp; ! 209: uint32_t next; ! 210: uint32_t be; ! 211: uint16_t offset[8]; ! 212: }; ! 213: ! 214: #define USB_HZ 12000000 ! 215: ! 216: /* OHCI Local stuff */ ! 217: #define OHCI_CTL_CBSR ((1<<0)|(1<<1)) ! 218: #define OHCI_CTL_PLE (1<<2) ! 219: #define OHCI_CTL_IE (1<<3) ! 220: #define OHCI_CTL_CLE (1<<4) ! 221: #define OHCI_CTL_BLE (1<<5) ! 222: #define OHCI_CTL_HCFS ((1<<6)|(1<<7)) ! 223: #define OHCI_USB_RESET 0x00 ! 224: #define OHCI_USB_RESUME 0x40 ! 225: #define OHCI_USB_OPERATIONAL 0x80 ! 226: #define OHCI_USB_SUSPEND 0xc0 ! 227: #define OHCI_CTL_IR (1<<8) ! 228: #define OHCI_CTL_RWC (1<<9) ! 229: #define OHCI_CTL_RWE (1<<10) ! 230: ! 231: #define OHCI_STATUS_HCR (1<<0) ! 232: #define OHCI_STATUS_CLF (1<<1) ! 233: #define OHCI_STATUS_BLF (1<<2) ! 234: #define OHCI_STATUS_OCR (1<<3) ! 235: #define OHCI_STATUS_SOC ((1<<6)|(1<<7)) ! 236: ! 237: #define OHCI_INTR_SO (1<<0) /* Scheduling overrun */ ! 238: #define OHCI_INTR_WD (1<<1) /* HcDoneHead writeback */ ! 239: #define OHCI_INTR_SF (1<<2) /* Start of frame */ ! 240: #define OHCI_INTR_RD (1<<3) /* Resume detect */ ! 241: #define OHCI_INTR_UE (1<<4) /* Unrecoverable error */ ! 242: #define OHCI_INTR_FNO (1<<5) /* Frame number overflow */ ! 243: #define OHCI_INTR_RHSC (1<<6) /* Root hub status change */ ! 244: #define OHCI_INTR_OC (1<<30) /* Ownership change */ ! 245: #define OHCI_INTR_MIE (1<<31) /* Master Interrupt Enable */ ! 246: ! 247: #define OHCI_HCCA_SIZE 0x100 ! 248: #define OHCI_HCCA_MASK 0xffffff00 ! 249: ! 250: #define OHCI_EDPTR_MASK 0xfffffff0 ! 251: ! 252: #define OHCI_FMI_FI 0x00003fff ! 253: #define OHCI_FMI_FSMPS 0xffff0000 ! 254: #define OHCI_FMI_FIT 0x80000000 ! 255: ! 256: #define OHCI_FR_RT (1<<31) ! 257: ! 258: #define OHCI_LS_THRESH 0x628 ! 259: ! 260: #define OHCI_RHA_RW_MASK 0x00000000 /* Mask of supported features. */ ! 261: #define OHCI_RHA_PSM (1<<8) ! 262: #define OHCI_RHA_NPS (1<<9) ! 263: #define OHCI_RHA_DT (1<<10) ! 264: #define OHCI_RHA_OCPM (1<<11) ! 265: #define OHCI_RHA_NOCP (1<<12) ! 266: #define OHCI_RHA_POTPGT_MASK 0xff000000 ! 267: ! 268: #define OHCI_RHS_LPS (1<<0) ! 269: #define OHCI_RHS_OCI (1<<1) ! 270: #define OHCI_RHS_DRWE (1<<15) ! 271: #define OHCI_RHS_LPSC (1<<16) ! 272: #define OHCI_RHS_OCIC (1<<17) ! 273: #define OHCI_RHS_CRWE (1<<31) ! 274: ! 275: #define OHCI_PORT_CCS (1<<0) ! 276: #define OHCI_PORT_PES (1<<1) ! 277: #define OHCI_PORT_PSS (1<<2) ! 278: #define OHCI_PORT_POCI (1<<3) ! 279: #define OHCI_PORT_PRS (1<<4) ! 280: #define OHCI_PORT_PPS (1<<8) ! 281: #define OHCI_PORT_LSDA (1<<9) ! 282: #define OHCI_PORT_CSC (1<<16) ! 283: #define OHCI_PORT_PESC (1<<17) ! 284: #define OHCI_PORT_PSSC (1<<18) ! 285: #define OHCI_PORT_OCIC (1<<19) ! 286: #define OHCI_PORT_PRSC (1<<20) ! 287: #define OHCI_PORT_WTC (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \ ! 288: |OHCI_PORT_OCIC|OHCI_PORT_PRSC) ! 289: ! 290: #define OHCI_TD_DIR_SETUP 0x0 ! 291: #define OHCI_TD_DIR_OUT 0x1 ! 292: #define OHCI_TD_DIR_IN 0x2 ! 293: #define OHCI_TD_DIR_RESERVED 0x3 ! 294: ! 295: #define OHCI_CC_NOERROR 0x0 ! 296: #define OHCI_CC_CRC 0x1 ! 297: #define OHCI_CC_BITSTUFFING 0x2 ! 298: #define OHCI_CC_DATATOGGLEMISMATCH 0x3 ! 299: #define OHCI_CC_STALL 0x4 ! 300: #define OHCI_CC_DEVICENOTRESPONDING 0x5 ! 301: #define OHCI_CC_PIDCHECKFAILURE 0x6 ! 302: #define OHCI_CC_UNDEXPETEDPID 0x7 ! 303: #define OHCI_CC_DATAOVERRUN 0x8 ! 304: #define OHCI_CC_DATAUNDERRUN 0x9 ! 305: #define OHCI_CC_BUFFEROVERRUN 0xc ! 306: #define OHCI_CC_BUFFERUNDERRUN 0xd ! 307: ! 308: #define OHCI_HRESET_FSBIR (1 << 0) ! 309: ! 310: /* Update IRQ levels */ ! 311: static inline void ohci_intr_update(OHCIState *ohci) ! 312: { ! 313: int level = 0; ! 314: ! 315: if ((ohci->intr & OHCI_INTR_MIE) && ! 316: (ohci->intr_status & ohci->intr)) ! 317: level = 1; ! 318: ! 319: qemu_set_irq(ohci->irq, level); ! 320: } ! 321: ! 322: /* Set an interrupt */ ! 323: static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr) ! 324: { ! 325: ohci->intr_status |= intr; ! 326: ohci_intr_update(ohci); ! 327: } ! 328: ! 329: /* Attach or detach a device on a root hub port. */ ! 330: static void ohci_attach(USBPort *port1) ! 331: { ! 332: OHCIState *s = port1->opaque; ! 333: OHCIPort *port = &s->rhport[port1->index]; ! 334: uint32_t old_state = port->ctrl; ! 335: ! 336: /* set connect status */ ! 337: port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC; ! 338: ! 339: /* update speed */ ! 340: if (port->port.dev->speed == USB_SPEED_LOW) { ! 341: port->ctrl |= OHCI_PORT_LSDA; ! 342: } else { ! 343: port->ctrl &= ~OHCI_PORT_LSDA; ! 344: } ! 345: ! 346: /* notify of remote-wakeup */ ! 347: if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) { ! 348: ohci_set_interrupt(s, OHCI_INTR_RD); ! 349: } ! 350: ! 351: DPRINTF("usb-ohci: Attached port %d\n", port1->index); ! 352: ! 353: if (old_state != port->ctrl) { ! 354: ohci_set_interrupt(s, OHCI_INTR_RHSC); ! 355: } ! 356: } ! 357: ! 358: static void ohci_detach(USBPort *port1) ! 359: { ! 360: OHCIState *s = port1->opaque; ! 361: OHCIPort *port = &s->rhport[port1->index]; ! 362: uint32_t old_state = port->ctrl; ! 363: ! 364: ohci_async_cancel_device(s, port1->dev); ! 365: ! 366: /* set connect status */ ! 367: if (port->ctrl & OHCI_PORT_CCS) { ! 368: port->ctrl &= ~OHCI_PORT_CCS; ! 369: port->ctrl |= OHCI_PORT_CSC; ! 370: } ! 371: /* disable port */ ! 372: if (port->ctrl & OHCI_PORT_PES) { ! 373: port->ctrl &= ~OHCI_PORT_PES; ! 374: port->ctrl |= OHCI_PORT_PESC; ! 375: } ! 376: DPRINTF("usb-ohci: Detached port %d\n", port1->index); ! 377: ! 378: if (old_state != port->ctrl) { ! 379: ohci_set_interrupt(s, OHCI_INTR_RHSC); ! 380: } ! 381: } ! 382: ! 383: static void ohci_wakeup(USBPort *port1) ! 384: { ! 385: OHCIState *s = port1->opaque; ! 386: OHCIPort *port = &s->rhport[port1->index]; ! 387: uint32_t intr = 0; ! 388: if (port->ctrl & OHCI_PORT_PSS) { ! 389: DPRINTF("usb-ohci: port %d: wakeup\n", port1->index); ! 390: port->ctrl |= OHCI_PORT_PSSC; ! 391: port->ctrl &= ~OHCI_PORT_PSS; ! 392: intr = OHCI_INTR_RHSC; ! 393: } ! 394: /* Note that the controller can be suspended even if this port is not */ ! 395: if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) { ! 396: DPRINTF("usb-ohci: remote-wakeup: SUSPEND->RESUME\n"); ! 397: /* This is the one state transition the controller can do by itself */ ! 398: s->ctl &= ~OHCI_CTL_HCFS; ! 399: s->ctl |= OHCI_USB_RESUME; ! 400: /* In suspend mode only ResumeDetected is possible, not RHSC: ! 401: * see the OHCI spec 5.1.2.3. ! 402: */ ! 403: intr = OHCI_INTR_RD; ! 404: } ! 405: ohci_set_interrupt(s, intr); ! 406: } ! 407: ! 408: static void ohci_child_detach(USBPort *port1, USBDevice *child) ! 409: { ! 410: OHCIState *s = port1->opaque; ! 411: ! 412: ohci_async_cancel_device(s, child); ! 413: } ! 414: ! 415: static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr) ! 416: { ! 417: USBDevice *dev; ! 418: int i; ! 419: ! 420: for (i = 0; i < ohci->num_ports; i++) { ! 421: if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) { ! 422: continue; ! 423: } ! 424: dev = usb_find_device(&ohci->rhport[i].port, addr); ! 425: if (dev != NULL) { ! 426: return dev; ! 427: } ! 428: } ! 429: return NULL; ! 430: } ! 431: ! 432: /* Reset the controller */ ! 433: static void ohci_reset(void *opaque) ! 434: { ! 435: OHCIState *ohci = opaque; ! 436: OHCIPort *port; ! 437: int i; ! 438: ! 439: ohci_bus_stop(ohci); ! 440: ohci->ctl = 0; ! 441: ohci->old_ctl = 0; ! 442: ohci->status = 0; ! 443: ohci->intr_status = 0; ! 444: ohci->intr = OHCI_INTR_MIE; ! 445: ! 446: ohci->hcca = 0; ! 447: ohci->ctrl_head = ohci->ctrl_cur = 0; ! 448: ohci->bulk_head = ohci->bulk_cur = 0; ! 449: ohci->per_cur = 0; ! 450: ohci->done = 0; ! 451: ohci->done_count = 7; ! 452: ! 453: /* FSMPS is marked TBD in OCHI 1.0, what gives ffs? ! 454: * I took the value linux sets ... ! 455: */ ! 456: ohci->fsmps = 0x2778; ! 457: ohci->fi = 0x2edf; ! 458: ohci->fit = 0; ! 459: ohci->frt = 0; ! 460: ohci->frame_number = 0; ! 461: ohci->pstart = 0; ! 462: ohci->lst = OHCI_LS_THRESH; ! 463: ! 464: ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports; ! 465: ohci->rhdesc_b = 0x0; /* Impl. specific */ ! 466: ohci->rhstatus = 0; ! 467: ! 468: for (i = 0; i < ohci->num_ports; i++) ! 469: { ! 470: port = &ohci->rhport[i]; ! 471: port->ctrl = 0; ! 472: if (port->port.dev && port->port.dev->attached) { ! 473: usb_port_reset(&port->port); ! 474: } ! 475: } ! 476: if (ohci->async_td) { ! 477: usb_cancel_packet(&ohci->usb_packet); ! 478: ohci->async_td = 0; ! 479: } ! 480: DPRINTF("usb-ohci: Reset %s\n", ohci->name); ! 481: } ! 482: ! 483: /* Get an array of dwords from main memory */ ! 484: static inline int get_dwords(OHCIState *ohci, ! 485: uint32_t addr, uint32_t *buf, int num) ! 486: { ! 487: int i; ! 488: ! 489: addr += ohci->localmem_base; ! 490: ! 491: for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { ! 492: cpu_physical_memory_read(addr, buf, sizeof(*buf)); ! 493: *buf = le32_to_cpu(*buf); ! 494: } ! 495: ! 496: return 1; ! 497: } ! 498: ! 499: /* Put an array of dwords in to main memory */ ! 500: static inline int put_dwords(OHCIState *ohci, ! 501: uint32_t addr, uint32_t *buf, int num) ! 502: { ! 503: int i; ! 504: ! 505: addr += ohci->localmem_base; ! 506: ! 507: for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { ! 508: uint32_t tmp = cpu_to_le32(*buf); ! 509: cpu_physical_memory_write(addr, &tmp, sizeof(tmp)); ! 510: } ! 511: ! 512: return 1; ! 513: } ! 514: ! 515: /* Get an array of words from main memory */ ! 516: static inline int get_words(OHCIState *ohci, ! 517: uint32_t addr, uint16_t *buf, int num) ! 518: { ! 519: int i; ! 520: ! 521: addr += ohci->localmem_base; ! 522: ! 523: for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { ! 524: cpu_physical_memory_read(addr, buf, sizeof(*buf)); ! 525: *buf = le16_to_cpu(*buf); ! 526: } ! 527: ! 528: return 1; ! 529: } ! 530: ! 531: /* Put an array of words in to main memory */ ! 532: static inline int put_words(OHCIState *ohci, ! 533: uint32_t addr, uint16_t *buf, int num) ! 534: { ! 535: int i; ! 536: ! 537: addr += ohci->localmem_base; ! 538: ! 539: for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { ! 540: uint16_t tmp = cpu_to_le16(*buf); ! 541: cpu_physical_memory_write(addr, &tmp, sizeof(tmp)); ! 542: } ! 543: ! 544: return 1; ! 545: } ! 546: ! 547: static inline int ohci_read_ed(OHCIState *ohci, ! 548: uint32_t addr, struct ohci_ed *ed) ! 549: { ! 550: return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2); ! 551: } ! 552: ! 553: static inline int ohci_read_td(OHCIState *ohci, ! 554: uint32_t addr, struct ohci_td *td) ! 555: { ! 556: return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2); ! 557: } ! 558: ! 559: static inline int ohci_read_iso_td(OHCIState *ohci, ! 560: uint32_t addr, struct ohci_iso_td *td) ! 561: { ! 562: return (get_dwords(ohci, addr, (uint32_t *)td, 4) && ! 563: get_words(ohci, addr + 16, td->offset, 8)); ! 564: } ! 565: ! 566: static inline int ohci_read_hcca(OHCIState *ohci, ! 567: uint32_t addr, struct ohci_hcca *hcca) ! 568: { ! 569: cpu_physical_memory_read(addr + ohci->localmem_base, hcca, sizeof(*hcca)); ! 570: return 1; ! 571: } ! 572: ! 573: static inline int ohci_put_ed(OHCIState *ohci, ! 574: uint32_t addr, struct ohci_ed *ed) ! 575: { ! 576: /* ed->tail is under control of the HCD. ! 577: * Since just ed->head is changed by HC, just write back this ! 578: */ ! 579: ! 580: return put_dwords(ohci, addr + ED_WBACK_OFFSET, ! 581: (uint32_t *)((char *)ed + ED_WBACK_OFFSET), ! 582: ED_WBACK_SIZE >> 2); ! 583: } ! 584: ! 585: static inline int ohci_put_td(OHCIState *ohci, ! 586: uint32_t addr, struct ohci_td *td) ! 587: { ! 588: return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2); ! 589: } ! 590: ! 591: static inline int ohci_put_iso_td(OHCIState *ohci, ! 592: uint32_t addr, struct ohci_iso_td *td) ! 593: { ! 594: return (put_dwords(ohci, addr, (uint32_t *)td, 4) && ! 595: put_words(ohci, addr + 16, td->offset, 8)); ! 596: } ! 597: ! 598: static inline int ohci_put_hcca(OHCIState *ohci, ! 599: uint32_t addr, struct ohci_hcca *hcca) ! 600: { ! 601: cpu_physical_memory_write(addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET, ! 602: (char *)hcca + HCCA_WRITEBACK_OFFSET, ! 603: HCCA_WRITEBACK_SIZE); ! 604: return 1; ! 605: } ! 606: ! 607: /* Read/Write the contents of a TD from/to main memory. */ ! 608: static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td, ! 609: uint8_t *buf, int len, int write) ! 610: { ! 611: uint32_t ptr; ! 612: uint32_t n; ! 613: ! 614: ptr = td->cbp; ! 615: n = 0x1000 - (ptr & 0xfff); ! 616: if (n > len) ! 617: n = len; ! 618: cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write); ! 619: if (n == len) ! 620: return; ! 621: ptr = td->be & ~0xfffu; ! 622: buf += n; ! 623: cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write); ! 624: } ! 625: ! 626: /* Read/Write the contents of an ISO TD from/to main memory. */ ! 627: static void ohci_copy_iso_td(OHCIState *ohci, ! 628: uint32_t start_addr, uint32_t end_addr, ! 629: uint8_t *buf, int len, int write) ! 630: { ! 631: uint32_t ptr; ! 632: uint32_t n; ! 633: ! 634: ptr = start_addr; ! 635: n = 0x1000 - (ptr & 0xfff); ! 636: if (n > len) ! 637: n = len; ! 638: cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write); ! 639: if (n == len) ! 640: return; ! 641: ptr = end_addr & ~0xfffu; ! 642: buf += n; ! 643: cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write); ! 644: } ! 645: ! 646: static void ohci_process_lists(OHCIState *ohci, int completion); ! 647: ! 648: static void ohci_async_complete_packet(USBPort *port, USBPacket *packet) ! 649: { ! 650: OHCIState *ohci = container_of(packet, OHCIState, usb_packet); ! 651: #ifdef DEBUG_PACKET ! 652: DPRINTF("Async packet complete\n"); ! 653: #endif ! 654: ohci->async_complete = 1; ! 655: ohci_process_lists(ohci, 1); ! 656: } ! 657: ! 658: #define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b))) ! 659: ! 660: static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, ! 661: int completion) ! 662: { ! 663: int dir; ! 664: size_t len = 0; ! 665: #ifdef DEBUG_ISOCH ! 666: const char *str = NULL; ! 667: #endif ! 668: int pid; ! 669: int ret; ! 670: int i; ! 671: USBDevice *dev; ! 672: USBEndpoint *ep; ! 673: struct ohci_iso_td iso_td; ! 674: uint32_t addr; ! 675: uint16_t starting_frame; ! 676: int16_t relative_frame_number; ! 677: int frame_count; ! 678: uint32_t start_offset, next_offset, end_offset = 0; ! 679: uint32_t start_addr, end_addr; ! 680: ! 681: addr = ed->head & OHCI_DPTR_MASK; ! 682: ! 683: if (!ohci_read_iso_td(ohci, addr, &iso_td)) { ! 684: printf("usb-ohci: ISO_TD read error at %x\n", addr); ! 685: return 0; ! 686: } ! 687: ! 688: starting_frame = OHCI_BM(iso_td.flags, TD_SF); ! 689: frame_count = OHCI_BM(iso_td.flags, TD_FC); ! 690: relative_frame_number = USUB(ohci->frame_number, starting_frame); ! 691: ! 692: #ifdef DEBUG_ISOCH ! 693: printf("--- ISO_TD ED head 0x%.8x tailp 0x%.8x\n" ! 694: "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" ! 695: "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" ! 696: "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" ! 697: "frame_number 0x%.8x starting_frame 0x%.8x\n" ! 698: "frame_count 0x%.8x relative %d\n" ! 699: "di 0x%.8x cc 0x%.8x\n", ! 700: ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK, ! 701: iso_td.flags, iso_td.bp, iso_td.next, iso_td.be, ! 702: iso_td.offset[0], iso_td.offset[1], iso_td.offset[2], iso_td.offset[3], ! 703: iso_td.offset[4], iso_td.offset[5], iso_td.offset[6], iso_td.offset[7], ! 704: ohci->frame_number, starting_frame, ! 705: frame_count, relative_frame_number, ! 706: OHCI_BM(iso_td.flags, TD_DI), OHCI_BM(iso_td.flags, TD_CC)); ! 707: #endif ! 708: ! 709: if (relative_frame_number < 0) { ! 710: DPRINTF("usb-ohci: ISO_TD R=%d < 0\n", relative_frame_number); ! 711: return 1; ! 712: } else if (relative_frame_number > frame_count) { ! 713: /* ISO TD expired - retire the TD to the Done Queue and continue with ! 714: the next ISO TD of the same ED */ ! 715: DPRINTF("usb-ohci: ISO_TD R=%d > FC=%d\n", relative_frame_number, ! 716: frame_count); ! 717: OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN); ! 718: ed->head &= ~OHCI_DPTR_MASK; ! 719: ed->head |= (iso_td.next & OHCI_DPTR_MASK); ! 720: iso_td.next = ohci->done; ! 721: ohci->done = addr; ! 722: i = OHCI_BM(iso_td.flags, TD_DI); ! 723: if (i < ohci->done_count) ! 724: ohci->done_count = i; ! 725: ohci_put_iso_td(ohci, addr, &iso_td); ! 726: return 0; ! 727: } ! 728: ! 729: dir = OHCI_BM(ed->flags, ED_D); ! 730: switch (dir) { ! 731: case OHCI_TD_DIR_IN: ! 732: #ifdef DEBUG_ISOCH ! 733: str = "in"; ! 734: #endif ! 735: pid = USB_TOKEN_IN; ! 736: break; ! 737: case OHCI_TD_DIR_OUT: ! 738: #ifdef DEBUG_ISOCH ! 739: str = "out"; ! 740: #endif ! 741: pid = USB_TOKEN_OUT; ! 742: break; ! 743: case OHCI_TD_DIR_SETUP: ! 744: #ifdef DEBUG_ISOCH ! 745: str = "setup"; ! 746: #endif ! 747: pid = USB_TOKEN_SETUP; ! 748: break; ! 749: default: ! 750: printf("usb-ohci: Bad direction %d\n", dir); ! 751: return 1; ! 752: } ! 753: ! 754: if (!iso_td.bp || !iso_td.be) { ! 755: printf("usb-ohci: ISO_TD bp 0x%.8x be 0x%.8x\n", iso_td.bp, iso_td.be); ! 756: return 1; ! 757: } ! 758: ! 759: start_offset = iso_td.offset[relative_frame_number]; ! 760: next_offset = iso_td.offset[relative_frame_number + 1]; ! 761: ! 762: if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) || ! 763: ((relative_frame_number < frame_count) && ! 764: !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) { ! 765: printf("usb-ohci: ISO_TD cc != not accessed 0x%.8x 0x%.8x\n", ! 766: start_offset, next_offset); ! 767: return 1; ! 768: } ! 769: ! 770: if ((relative_frame_number < frame_count) && (start_offset > next_offset)) { ! 771: printf("usb-ohci: ISO_TD start_offset=0x%.8x > next_offset=0x%.8x\n", ! 772: start_offset, next_offset); ! 773: return 1; ! 774: } ! 775: ! 776: if ((start_offset & 0x1000) == 0) { ! 777: start_addr = (iso_td.bp & OHCI_PAGE_MASK) | ! 778: (start_offset & OHCI_OFFSET_MASK); ! 779: } else { ! 780: start_addr = (iso_td.be & OHCI_PAGE_MASK) | ! 781: (start_offset & OHCI_OFFSET_MASK); ! 782: } ! 783: ! 784: if (relative_frame_number < frame_count) { ! 785: end_offset = next_offset - 1; ! 786: if ((end_offset & 0x1000) == 0) { ! 787: end_addr = (iso_td.bp & OHCI_PAGE_MASK) | ! 788: (end_offset & OHCI_OFFSET_MASK); ! 789: } else { ! 790: end_addr = (iso_td.be & OHCI_PAGE_MASK) | ! 791: (end_offset & OHCI_OFFSET_MASK); ! 792: } ! 793: } else { ! 794: /* Last packet in the ISO TD */ ! 795: end_addr = iso_td.be; ! 796: } ! 797: ! 798: if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) { ! 799: len = (end_addr & OHCI_OFFSET_MASK) + 0x1001 ! 800: - (start_addr & OHCI_OFFSET_MASK); ! 801: } else { ! 802: len = end_addr - start_addr + 1; ! 803: } ! 804: ! 805: if (len && dir != OHCI_TD_DIR_IN) { ! 806: ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len, 0); ! 807: } ! 808: ! 809: if (completion) { ! 810: ret = ohci->usb_packet.result; ! 811: } else { ! 812: dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); ! 813: ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); ! 814: usb_packet_setup(&ohci->usb_packet, pid, ep); ! 815: usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len); ! 816: ret = usb_handle_packet(dev, &ohci->usb_packet); ! 817: if (ret == USB_RET_ASYNC) { ! 818: return 1; ! 819: } ! 820: } ! 821: ! 822: #ifdef DEBUG_ISOCH ! 823: printf("so 0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d\n", ! 824: start_offset, end_offset, start_addr, end_addr, str, len, ret); ! 825: #endif ! 826: ! 827: /* Writeback */ ! 828: if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) { ! 829: /* IN transfer succeeded */ ! 830: ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret, 1); ! 831: OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, ! 832: OHCI_CC_NOERROR); ! 833: OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret); ! 834: } else if (dir == OHCI_TD_DIR_OUT && ret == len) { ! 835: /* OUT transfer succeeded */ ! 836: OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, ! 837: OHCI_CC_NOERROR); ! 838: OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0); ! 839: } else { ! 840: if (ret > (ssize_t) len) { ! 841: printf("usb-ohci: DataOverrun %d > %zu\n", ret, len); ! 842: OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, ! 843: OHCI_CC_DATAOVERRUN); ! 844: OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ! 845: len); ! 846: } else if (ret >= 0) { ! 847: printf("usb-ohci: DataUnderrun %d\n", ret); ! 848: OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, ! 849: OHCI_CC_DATAUNDERRUN); ! 850: } else { ! 851: switch (ret) { ! 852: case USB_RET_IOERROR: ! 853: case USB_RET_NODEV: ! 854: OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, ! 855: OHCI_CC_DEVICENOTRESPONDING); ! 856: OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ! 857: 0); ! 858: break; ! 859: case USB_RET_NAK: ! 860: case USB_RET_STALL: ! 861: printf("usb-ohci: got NAK/STALL %d\n", ret); ! 862: OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, ! 863: OHCI_CC_STALL); ! 864: OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ! 865: 0); ! 866: break; ! 867: default: ! 868: printf("usb-ohci: Bad device response %d\n", ret); ! 869: OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, ! 870: OHCI_CC_UNDEXPETEDPID); ! 871: break; ! 872: } ! 873: } ! 874: } ! 875: ! 876: if (relative_frame_number == frame_count) { ! 877: /* Last data packet of ISO TD - retire the TD to the Done Queue */ ! 878: OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR); ! 879: ed->head &= ~OHCI_DPTR_MASK; ! 880: ed->head |= (iso_td.next & OHCI_DPTR_MASK); ! 881: iso_td.next = ohci->done; ! 882: ohci->done = addr; ! 883: i = OHCI_BM(iso_td.flags, TD_DI); ! 884: if (i < ohci->done_count) ! 885: ohci->done_count = i; ! 886: } ! 887: ohci_put_iso_td(ohci, addr, &iso_td); ! 888: return 1; ! 889: } ! 890: ! 891: /* Service a transport descriptor. ! 892: Returns nonzero to terminate processing of this endpoint. */ ! 893: ! 894: static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) ! 895: { ! 896: int dir; ! 897: size_t len = 0, pktlen = 0; ! 898: #ifdef DEBUG_PACKET ! 899: const char *str = NULL; ! 900: #endif ! 901: int pid; ! 902: int ret; ! 903: int i; ! 904: USBDevice *dev; ! 905: USBEndpoint *ep; ! 906: struct ohci_td td; ! 907: uint32_t addr; ! 908: int flag_r; ! 909: int completion; ! 910: ! 911: addr = ed->head & OHCI_DPTR_MASK; ! 912: /* See if this TD has already been submitted to the device. */ ! 913: completion = (addr == ohci->async_td); ! 914: if (completion && !ohci->async_complete) { ! 915: #ifdef DEBUG_PACKET ! 916: DPRINTF("Skipping async TD\n"); ! 917: #endif ! 918: return 1; ! 919: } ! 920: if (!ohci_read_td(ohci, addr, &td)) { ! 921: fprintf(stderr, "usb-ohci: TD read error at %x\n", addr); ! 922: return 0; ! 923: } ! 924: ! 925: dir = OHCI_BM(ed->flags, ED_D); ! 926: switch (dir) { ! 927: case OHCI_TD_DIR_OUT: ! 928: case OHCI_TD_DIR_IN: ! 929: /* Same value. */ ! 930: break; ! 931: default: ! 932: dir = OHCI_BM(td.flags, TD_DP); ! 933: break; ! 934: } ! 935: ! 936: switch (dir) { ! 937: case OHCI_TD_DIR_IN: ! 938: #ifdef DEBUG_PACKET ! 939: str = "in"; ! 940: #endif ! 941: pid = USB_TOKEN_IN; ! 942: break; ! 943: case OHCI_TD_DIR_OUT: ! 944: #ifdef DEBUG_PACKET ! 945: str = "out"; ! 946: #endif ! 947: pid = USB_TOKEN_OUT; ! 948: break; ! 949: case OHCI_TD_DIR_SETUP: ! 950: #ifdef DEBUG_PACKET ! 951: str = "setup"; ! 952: #endif ! 953: pid = USB_TOKEN_SETUP; ! 954: break; ! 955: default: ! 956: fprintf(stderr, "usb-ohci: Bad direction\n"); ! 957: return 1; ! 958: } ! 959: if (td.cbp && td.be) { ! 960: if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) { ! 961: len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff); ! 962: } else { ! 963: len = (td.be - td.cbp) + 1; ! 964: } ! 965: ! 966: pktlen = len; ! 967: if (len && dir != OHCI_TD_DIR_IN) { ! 968: /* The endpoint may not allow us to transfer it all now */ ! 969: pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT; ! 970: if (pktlen > len) { ! 971: pktlen = len; ! 972: } ! 973: if (!completion) { ! 974: ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen, 0); ! 975: } ! 976: } ! 977: } ! 978: ! 979: flag_r = (td.flags & OHCI_TD_R) != 0; ! 980: #ifdef DEBUG_PACKET ! 981: DPRINTF(" TD @ 0x%.8x %" PRId64 " of %" PRId64 ! 982: " bytes %s r=%d cbp=0x%.8x be=0x%.8x\n", ! 983: addr, (int64_t)pktlen, (int64_t)len, str, flag_r, td.cbp, td.be); ! 984: ! 985: if (pktlen > 0 && dir != OHCI_TD_DIR_IN) { ! 986: DPRINTF(" data:"); ! 987: for (i = 0; i < pktlen; i++) { ! 988: printf(" %.2x", ohci->usb_buf[i]); ! 989: } ! 990: DPRINTF("\n"); ! 991: } ! 992: #endif ! 993: if (completion) { ! 994: ret = ohci->usb_packet.result; ! 995: ohci->async_td = 0; ! 996: ohci->async_complete = 0; ! 997: } else { ! 998: if (ohci->async_td) { ! 999: /* ??? The hardware should allow one active packet per ! 1000: endpoint. We only allow one active packet per controller. ! 1001: This should be sufficient as long as devices respond in a ! 1002: timely manner. ! 1003: */ ! 1004: #ifdef DEBUG_PACKET ! 1005: DPRINTF("Too many pending packets\n"); ! 1006: #endif ! 1007: return 1; ! 1008: } ! 1009: dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); ! 1010: ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); ! 1011: usb_packet_setup(&ohci->usb_packet, pid, ep); ! 1012: usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen); ! 1013: ret = usb_handle_packet(dev, &ohci->usb_packet); ! 1014: #ifdef DEBUG_PACKET ! 1015: DPRINTF("ret=%d\n", ret); ! 1016: #endif ! 1017: if (ret == USB_RET_ASYNC) { ! 1018: ohci->async_td = addr; ! 1019: return 1; ! 1020: } ! 1021: } ! 1022: if (ret >= 0) { ! 1023: if (dir == OHCI_TD_DIR_IN) { ! 1024: ohci_copy_td(ohci, &td, ohci->usb_buf, ret, 1); ! 1025: #ifdef DEBUG_PACKET ! 1026: DPRINTF(" data:"); ! 1027: for (i = 0; i < ret; i++) ! 1028: printf(" %.2x", ohci->usb_buf[i]); ! 1029: DPRINTF("\n"); ! 1030: #endif ! 1031: } else { ! 1032: ret = pktlen; ! 1033: } ! 1034: } ! 1035: ! 1036: /* Writeback */ ! 1037: if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) { ! 1038: /* Transmission succeeded. */ ! 1039: if (ret == len) { ! 1040: td.cbp = 0; ! 1041: } else { ! 1042: if ((td.cbp & 0xfff) + ret > 0xfff) { ! 1043: td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff); ! 1044: } else { ! 1045: td.cbp += ret; ! 1046: } ! 1047: } ! 1048: td.flags |= OHCI_TD_T1; ! 1049: td.flags ^= OHCI_TD_T0; ! 1050: OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR); ! 1051: OHCI_SET_BM(td.flags, TD_EC, 0); ! 1052: ! 1053: if ((dir != OHCI_TD_DIR_IN) && (ret != len)) { ! 1054: /* Partial packet transfer: TD not ready to retire yet */ ! 1055: goto exit_no_retire; ! 1056: } ! 1057: ! 1058: /* Setting ED_C is part of the TD retirement process */ ! 1059: ed->head &= ~OHCI_ED_C; ! 1060: if (td.flags & OHCI_TD_T0) ! 1061: ed->head |= OHCI_ED_C; ! 1062: } else { ! 1063: if (ret >= 0) { ! 1064: DPRINTF("usb-ohci: Underrun\n"); ! 1065: OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN); ! 1066: } else { ! 1067: switch (ret) { ! 1068: case USB_RET_IOERROR: ! 1069: case USB_RET_NODEV: ! 1070: OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING); ! 1071: case USB_RET_NAK: ! 1072: DPRINTF("usb-ohci: got NAK\n"); ! 1073: return 1; ! 1074: case USB_RET_STALL: ! 1075: DPRINTF("usb-ohci: got STALL\n"); ! 1076: OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL); ! 1077: break; ! 1078: case USB_RET_BABBLE: ! 1079: DPRINTF("usb-ohci: got BABBLE\n"); ! 1080: OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN); ! 1081: break; ! 1082: default: ! 1083: fprintf(stderr, "usb-ohci: Bad device response %d\n", ret); ! 1084: OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID); ! 1085: OHCI_SET_BM(td.flags, TD_EC, 3); ! 1086: break; ! 1087: } ! 1088: } ! 1089: ed->head |= OHCI_ED_H; ! 1090: } ! 1091: ! 1092: /* Retire this TD */ ! 1093: ed->head &= ~OHCI_DPTR_MASK; ! 1094: ed->head |= td.next & OHCI_DPTR_MASK; ! 1095: td.next = ohci->done; ! 1096: ohci->done = addr; ! 1097: i = OHCI_BM(td.flags, TD_DI); ! 1098: if (i < ohci->done_count) ! 1099: ohci->done_count = i; ! 1100: exit_no_retire: ! 1101: ohci_put_td(ohci, addr, &td); ! 1102: return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR; ! 1103: } ! 1104: ! 1105: /* Service an endpoint list. Returns nonzero if active TD were found. */ ! 1106: static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion) ! 1107: { ! 1108: struct ohci_ed ed; ! 1109: uint32_t next_ed; ! 1110: uint32_t cur; ! 1111: int active; ! 1112: ! 1113: active = 0; ! 1114: ! 1115: if (head == 0) ! 1116: return 0; ! 1117: ! 1118: for (cur = head; cur; cur = next_ed) { ! 1119: if (!ohci_read_ed(ohci, cur, &ed)) { ! 1120: fprintf(stderr, "usb-ohci: ED read error at %x\n", cur); ! 1121: return 0; ! 1122: } ! 1123: ! 1124: next_ed = ed.next & OHCI_DPTR_MASK; ! 1125: ! 1126: if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) { ! 1127: uint32_t addr; ! 1128: /* Cancel pending packets for ED that have been paused. */ ! 1129: addr = ed.head & OHCI_DPTR_MASK; ! 1130: if (ohci->async_td && addr == ohci->async_td) { ! 1131: usb_cancel_packet(&ohci->usb_packet); ! 1132: ohci->async_td = 0; ! 1133: } ! 1134: continue; ! 1135: } ! 1136: ! 1137: while ((ed.head & OHCI_DPTR_MASK) != ed.tail) { ! 1138: #ifdef DEBUG_PACKET ! 1139: DPRINTF("ED @ 0x%.8x fa=%u en=%u d=%u s=%u k=%u f=%u mps=%u " ! 1140: "h=%u c=%u\n head=0x%.8x tailp=0x%.8x next=0x%.8x\n", cur, ! 1141: OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN), ! 1142: OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0, ! 1143: (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0, ! 1144: OHCI_BM(ed.flags, ED_MPS), (ed.head & OHCI_ED_H) != 0, ! 1145: (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK, ! 1146: ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK); ! 1147: #endif ! 1148: active = 1; ! 1149: ! 1150: if ((ed.flags & OHCI_ED_F) == 0) { ! 1151: if (ohci_service_td(ohci, &ed)) ! 1152: break; ! 1153: } else { ! 1154: /* Handle isochronous endpoints */ ! 1155: if (ohci_service_iso_td(ohci, &ed, completion)) ! 1156: break; ! 1157: } ! 1158: } ! 1159: ! 1160: ohci_put_ed(ohci, cur, &ed); ! 1161: } ! 1162: ! 1163: return active; ! 1164: } ! 1165: ! 1166: /* Generate a SOF event, and set a timer for EOF */ ! 1167: static void ohci_sof(OHCIState *ohci) ! 1168: { ! 1169: ohci->sof_time = qemu_get_clock_ns(vm_clock); ! 1170: qemu_mod_timer(ohci->eof_timer, ohci->sof_time + usb_frame_time); ! 1171: ohci_set_interrupt(ohci, OHCI_INTR_SF); ! 1172: } ! 1173: ! 1174: /* Process Control and Bulk lists. */ ! 1175: static void ohci_process_lists(OHCIState *ohci, int completion) ! 1176: { ! 1177: if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) { ! 1178: if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) { ! 1179: DPRINTF("usb-ohci: head %x, cur %x\n", ! 1180: ohci->ctrl_head, ohci->ctrl_cur); ! 1181: } ! 1182: if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) { ! 1183: ohci->ctrl_cur = 0; ! 1184: ohci->status &= ~OHCI_STATUS_CLF; ! 1185: } ! 1186: } ! 1187: ! 1188: if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) { ! 1189: if (!ohci_service_ed_list(ohci, ohci->bulk_head, completion)) { ! 1190: ohci->bulk_cur = 0; ! 1191: ohci->status &= ~OHCI_STATUS_BLF; ! 1192: } ! 1193: } ! 1194: } ! 1195: ! 1196: /* Do frame processing on frame boundary */ ! 1197: static void ohci_frame_boundary(void *opaque) ! 1198: { ! 1199: OHCIState *ohci = opaque; ! 1200: struct ohci_hcca hcca; ! 1201: ! 1202: ohci_read_hcca(ohci, ohci->hcca, &hcca); ! 1203: ! 1204: /* Process all the lists at the end of the frame */ ! 1205: if (ohci->ctl & OHCI_CTL_PLE) { ! 1206: int n; ! 1207: ! 1208: n = ohci->frame_number & 0x1f; ! 1209: ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]), 0); ! 1210: } ! 1211: ! 1212: /* Cancel all pending packets if either of the lists has been disabled. */ ! 1213: if (ohci->async_td && ! 1214: ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) { ! 1215: usb_cancel_packet(&ohci->usb_packet); ! 1216: ohci->async_td = 0; ! 1217: } ! 1218: ohci->old_ctl = ohci->ctl; ! 1219: ohci_process_lists(ohci, 0); ! 1220: ! 1221: /* Frame boundary, so do EOF stuf here */ ! 1222: ohci->frt = ohci->fit; ! 1223: ! 1224: /* Increment frame number and take care of endianness. */ ! 1225: ohci->frame_number = (ohci->frame_number + 1) & 0xffff; ! 1226: hcca.frame = cpu_to_le16(ohci->frame_number); ! 1227: ! 1228: if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) { ! 1229: if (!ohci->done) ! 1230: abort(); ! 1231: if (ohci->intr & ohci->intr_status) ! 1232: ohci->done |= 1; ! 1233: hcca.done = cpu_to_le32(ohci->done); ! 1234: ohci->done = 0; ! 1235: ohci->done_count = 7; ! 1236: ohci_set_interrupt(ohci, OHCI_INTR_WD); ! 1237: } ! 1238: ! 1239: if (ohci->done_count != 7 && ohci->done_count != 0) ! 1240: ohci->done_count--; ! 1241: ! 1242: /* Do SOF stuff here */ ! 1243: ohci_sof(ohci); ! 1244: ! 1245: /* Writeback HCCA */ ! 1246: ohci_put_hcca(ohci, ohci->hcca, &hcca); ! 1247: } ! 1248: ! 1249: /* Start sending SOF tokens across the USB bus, lists are processed in ! 1250: * next frame ! 1251: */ ! 1252: static int ohci_bus_start(OHCIState *ohci) ! 1253: { ! 1254: ohci->eof_timer = qemu_new_timer_ns(vm_clock, ! 1255: ohci_frame_boundary, ! 1256: ohci); ! 1257: ! 1258: if (ohci->eof_timer == NULL) { ! 1259: fprintf(stderr, "usb-ohci: %s: qemu_new_timer_ns failed\n", ohci->name); ! 1260: /* TODO: Signal unrecoverable error */ ! 1261: return 0; ! 1262: } ! 1263: ! 1264: DPRINTF("usb-ohci: %s: USB Operational\n", ohci->name); ! 1265: ! 1266: ohci_sof(ohci); ! 1267: ! 1268: return 1; ! 1269: } ! 1270: ! 1271: /* Stop sending SOF tokens on the bus */ ! 1272: static void ohci_bus_stop(OHCIState *ohci) ! 1273: { ! 1274: if (ohci->eof_timer) ! 1275: qemu_del_timer(ohci->eof_timer); ! 1276: ohci->eof_timer = NULL; ! 1277: } ! 1278: ! 1279: /* Sets a flag in a port status register but only set it if the port is ! 1280: * connected, if not set ConnectStatusChange flag. If flag is enabled ! 1281: * return 1. ! 1282: */ ! 1283: static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val) ! 1284: { ! 1285: int ret = 1; ! 1286: ! 1287: /* writing a 0 has no effect */ ! 1288: if (val == 0) ! 1289: return 0; ! 1290: ! 1291: /* If CurrentConnectStatus is cleared we set ! 1292: * ConnectStatusChange ! 1293: */ ! 1294: if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) { ! 1295: ohci->rhport[i].ctrl |= OHCI_PORT_CSC; ! 1296: if (ohci->rhstatus & OHCI_RHS_DRWE) { ! 1297: /* TODO: CSC is a wakeup event */ ! 1298: } ! 1299: return 0; ! 1300: } ! 1301: ! 1302: if (ohci->rhport[i].ctrl & val) ! 1303: ret = 0; ! 1304: ! 1305: /* set the bit */ ! 1306: ohci->rhport[i].ctrl |= val; ! 1307: ! 1308: return ret; ! 1309: } ! 1310: ! 1311: /* Set the frame interval - frame interval toggle is manipulated by the hcd only */ ! 1312: static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val) ! 1313: { ! 1314: val &= OHCI_FMI_FI; ! 1315: ! 1316: if (val != ohci->fi) { ! 1317: DPRINTF("usb-ohci: %s: FrameInterval = 0x%x (%u)\n", ! 1318: ohci->name, ohci->fi, ohci->fi); ! 1319: } ! 1320: ! 1321: ohci->fi = val; ! 1322: } ! 1323: ! 1324: static void ohci_port_power(OHCIState *ohci, int i, int p) ! 1325: { ! 1326: if (p) { ! 1327: ohci->rhport[i].ctrl |= OHCI_PORT_PPS; ! 1328: } else { ! 1329: ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS| ! 1330: OHCI_PORT_CCS| ! 1331: OHCI_PORT_PSS| ! 1332: OHCI_PORT_PRS); ! 1333: } ! 1334: } ! 1335: ! 1336: /* Set HcControlRegister */ ! 1337: static void ohci_set_ctl(OHCIState *ohci, uint32_t val) ! 1338: { ! 1339: uint32_t old_state; ! 1340: uint32_t new_state; ! 1341: ! 1342: old_state = ohci->ctl & OHCI_CTL_HCFS; ! 1343: ohci->ctl = val; ! 1344: new_state = ohci->ctl & OHCI_CTL_HCFS; ! 1345: ! 1346: /* no state change */ ! 1347: if (old_state == new_state) ! 1348: return; ! 1349: ! 1350: switch (new_state) { ! 1351: case OHCI_USB_OPERATIONAL: ! 1352: ohci_bus_start(ohci); ! 1353: break; ! 1354: case OHCI_USB_SUSPEND: ! 1355: ohci_bus_stop(ohci); ! 1356: DPRINTF("usb-ohci: %s: USB Suspended\n", ohci->name); ! 1357: break; ! 1358: case OHCI_USB_RESUME: ! 1359: DPRINTF("usb-ohci: %s: USB Resume\n", ohci->name); ! 1360: break; ! 1361: case OHCI_USB_RESET: ! 1362: ohci_reset(ohci); ! 1363: DPRINTF("usb-ohci: %s: USB Reset\n", ohci->name); ! 1364: break; ! 1365: } ! 1366: } ! 1367: ! 1368: static uint32_t ohci_get_frame_remaining(OHCIState *ohci) ! 1369: { ! 1370: uint16_t fr; ! 1371: int64_t tks; ! 1372: ! 1373: if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL) ! 1374: return (ohci->frt << 31); ! 1375: ! 1376: /* Being in USB operational state guarnatees sof_time was ! 1377: * set already. ! 1378: */ ! 1379: tks = qemu_get_clock_ns(vm_clock) - ohci->sof_time; ! 1380: ! 1381: /* avoid muldiv if possible */ ! 1382: if (tks >= usb_frame_time) ! 1383: return (ohci->frt << 31); ! 1384: ! 1385: tks = muldiv64(1, tks, usb_bit_time); ! 1386: fr = (uint16_t)(ohci->fi - tks); ! 1387: ! 1388: return (ohci->frt << 31) | fr; ! 1389: } ! 1390: ! 1391: ! 1392: /* Set root hub status */ ! 1393: static void ohci_set_hub_status(OHCIState *ohci, uint32_t val) ! 1394: { ! 1395: uint32_t old_state; ! 1396: ! 1397: old_state = ohci->rhstatus; ! 1398: ! 1399: /* write 1 to clear OCIC */ ! 1400: if (val & OHCI_RHS_OCIC) ! 1401: ohci->rhstatus &= ~OHCI_RHS_OCIC; ! 1402: ! 1403: if (val & OHCI_RHS_LPS) { ! 1404: int i; ! 1405: ! 1406: for (i = 0; i < ohci->num_ports; i++) ! 1407: ohci_port_power(ohci, i, 0); ! 1408: DPRINTF("usb-ohci: powered down all ports\n"); ! 1409: } ! 1410: ! 1411: if (val & OHCI_RHS_LPSC) { ! 1412: int i; ! 1413: ! 1414: for (i = 0; i < ohci->num_ports; i++) ! 1415: ohci_port_power(ohci, i, 1); ! 1416: DPRINTF("usb-ohci: powered up all ports\n"); ! 1417: } ! 1418: ! 1419: if (val & OHCI_RHS_DRWE) ! 1420: ohci->rhstatus |= OHCI_RHS_DRWE; ! 1421: ! 1422: if (val & OHCI_RHS_CRWE) ! 1423: ohci->rhstatus &= ~OHCI_RHS_DRWE; ! 1424: ! 1425: if (old_state != ohci->rhstatus) ! 1426: ohci_set_interrupt(ohci, OHCI_INTR_RHSC); ! 1427: } ! 1428: ! 1429: /* Set root hub port status */ ! 1430: static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val) ! 1431: { ! 1432: uint32_t old_state; ! 1433: OHCIPort *port; ! 1434: ! 1435: port = &ohci->rhport[portnum]; ! 1436: old_state = port->ctrl; ! 1437: ! 1438: /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */ ! 1439: if (val & OHCI_PORT_WTC) ! 1440: port->ctrl &= ~(val & OHCI_PORT_WTC); ! 1441: ! 1442: if (val & OHCI_PORT_CCS) ! 1443: port->ctrl &= ~OHCI_PORT_PES; ! 1444: ! 1445: ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES); ! 1446: ! 1447: if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) { ! 1448: DPRINTF("usb-ohci: port %d: SUSPEND\n", portnum); ! 1449: } ! 1450: ! 1451: if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) { ! 1452: DPRINTF("usb-ohci: port %d: RESET\n", portnum); ! 1453: usb_device_reset(port->port.dev); ! 1454: port->ctrl &= ~OHCI_PORT_PRS; ! 1455: /* ??? Should this also set OHCI_PORT_PESC. */ ! 1456: port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC; ! 1457: } ! 1458: ! 1459: /* Invert order here to ensure in ambiguous case, device is ! 1460: * powered up... ! 1461: */ ! 1462: if (val & OHCI_PORT_LSDA) ! 1463: ohci_port_power(ohci, portnum, 0); ! 1464: if (val & OHCI_PORT_PPS) ! 1465: ohci_port_power(ohci, portnum, 1); ! 1466: ! 1467: if (old_state != port->ctrl) ! 1468: ohci_set_interrupt(ohci, OHCI_INTR_RHSC); ! 1469: ! 1470: return; ! 1471: } ! 1472: ! 1473: static uint64_t ohci_mem_read(void *opaque, ! 1474: target_phys_addr_t addr, ! 1475: unsigned size) ! 1476: { ! 1477: OHCIState *ohci = opaque; ! 1478: uint32_t retval; ! 1479: ! 1480: /* Only aligned reads are allowed on OHCI */ ! 1481: if (addr & 3) { ! 1482: fprintf(stderr, "usb-ohci: Mis-aligned read\n"); ! 1483: return 0xffffffff; ! 1484: } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) { ! 1485: /* HcRhPortStatus */ ! 1486: retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS; ! 1487: } else { ! 1488: switch (addr >> 2) { ! 1489: case 0: /* HcRevision */ ! 1490: retval = 0x10; ! 1491: break; ! 1492: ! 1493: case 1: /* HcControl */ ! 1494: retval = ohci->ctl; ! 1495: break; ! 1496: ! 1497: case 2: /* HcCommandStatus */ ! 1498: retval = ohci->status; ! 1499: break; ! 1500: ! 1501: case 3: /* HcInterruptStatus */ ! 1502: retval = ohci->intr_status; ! 1503: break; ! 1504: ! 1505: case 4: /* HcInterruptEnable */ ! 1506: case 5: /* HcInterruptDisable */ ! 1507: retval = ohci->intr; ! 1508: break; ! 1509: ! 1510: case 6: /* HcHCCA */ ! 1511: retval = ohci->hcca; ! 1512: break; ! 1513: ! 1514: case 7: /* HcPeriodCurrentED */ ! 1515: retval = ohci->per_cur; ! 1516: break; ! 1517: ! 1518: case 8: /* HcControlHeadED */ ! 1519: retval = ohci->ctrl_head; ! 1520: break; ! 1521: ! 1522: case 9: /* HcControlCurrentED */ ! 1523: retval = ohci->ctrl_cur; ! 1524: break; ! 1525: ! 1526: case 10: /* HcBulkHeadED */ ! 1527: retval = ohci->bulk_head; ! 1528: break; ! 1529: ! 1530: case 11: /* HcBulkCurrentED */ ! 1531: retval = ohci->bulk_cur; ! 1532: break; ! 1533: ! 1534: case 12: /* HcDoneHead */ ! 1535: retval = ohci->done; ! 1536: break; ! 1537: ! 1538: case 13: /* HcFmInterretval */ ! 1539: retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi); ! 1540: break; ! 1541: ! 1542: case 14: /* HcFmRemaining */ ! 1543: retval = ohci_get_frame_remaining(ohci); ! 1544: break; ! 1545: ! 1546: case 15: /* HcFmNumber */ ! 1547: retval = ohci->frame_number; ! 1548: break; ! 1549: ! 1550: case 16: /* HcPeriodicStart */ ! 1551: retval = ohci->pstart; ! 1552: break; ! 1553: ! 1554: case 17: /* HcLSThreshold */ ! 1555: retval = ohci->lst; ! 1556: break; ! 1557: ! 1558: case 18: /* HcRhDescriptorA */ ! 1559: retval = ohci->rhdesc_a; ! 1560: break; ! 1561: ! 1562: case 19: /* HcRhDescriptorB */ ! 1563: retval = ohci->rhdesc_b; ! 1564: break; ! 1565: ! 1566: case 20: /* HcRhStatus */ ! 1567: retval = ohci->rhstatus; ! 1568: break; ! 1569: ! 1570: /* PXA27x specific registers */ ! 1571: case 24: /* HcStatus */ ! 1572: retval = ohci->hstatus & ohci->hmask; ! 1573: break; ! 1574: ! 1575: case 25: /* HcHReset */ ! 1576: retval = ohci->hreset; ! 1577: break; ! 1578: ! 1579: case 26: /* HcHInterruptEnable */ ! 1580: retval = ohci->hmask; ! 1581: break; ! 1582: ! 1583: case 27: /* HcHInterruptTest */ ! 1584: retval = ohci->htest; ! 1585: break; ! 1586: ! 1587: default: ! 1588: fprintf(stderr, "ohci_read: Bad offset %x\n", (int)addr); ! 1589: retval = 0xffffffff; ! 1590: } ! 1591: } ! 1592: ! 1593: return retval; ! 1594: } ! 1595: ! 1596: static void ohci_mem_write(void *opaque, ! 1597: target_phys_addr_t addr, ! 1598: uint64_t val, ! 1599: unsigned size) ! 1600: { ! 1601: OHCIState *ohci = opaque; ! 1602: ! 1603: /* Only aligned reads are allowed on OHCI */ ! 1604: if (addr & 3) { ! 1605: fprintf(stderr, "usb-ohci: Mis-aligned write\n"); ! 1606: return; ! 1607: } ! 1608: ! 1609: if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) { ! 1610: /* HcRhPortStatus */ ! 1611: ohci_port_set_status(ohci, (addr - 0x54) >> 2, val); ! 1612: return; ! 1613: } ! 1614: ! 1615: switch (addr >> 2) { ! 1616: case 1: /* HcControl */ ! 1617: ohci_set_ctl(ohci, val); ! 1618: break; ! 1619: ! 1620: case 2: /* HcCommandStatus */ ! 1621: /* SOC is read-only */ ! 1622: val = (val & ~OHCI_STATUS_SOC); ! 1623: ! 1624: /* Bits written as '0' remain unchanged in the register */ ! 1625: ohci->status |= val; ! 1626: ! 1627: if (ohci->status & OHCI_STATUS_HCR) ! 1628: ohci_reset(ohci); ! 1629: break; ! 1630: ! 1631: case 3: /* HcInterruptStatus */ ! 1632: ohci->intr_status &= ~val; ! 1633: ohci_intr_update(ohci); ! 1634: break; ! 1635: ! 1636: case 4: /* HcInterruptEnable */ ! 1637: ohci->intr |= val; ! 1638: ohci_intr_update(ohci); ! 1639: break; ! 1640: ! 1641: case 5: /* HcInterruptDisable */ ! 1642: ohci->intr &= ~val; ! 1643: ohci_intr_update(ohci); ! 1644: break; ! 1645: ! 1646: case 6: /* HcHCCA */ ! 1647: ohci->hcca = val & OHCI_HCCA_MASK; ! 1648: break; ! 1649: ! 1650: case 7: /* HcPeriodCurrentED */ ! 1651: /* Ignore writes to this read-only register, Linux does them */ ! 1652: break; ! 1653: ! 1654: case 8: /* HcControlHeadED */ ! 1655: ohci->ctrl_head = val & OHCI_EDPTR_MASK; ! 1656: break; ! 1657: ! 1658: case 9: /* HcControlCurrentED */ ! 1659: ohci->ctrl_cur = val & OHCI_EDPTR_MASK; ! 1660: break; ! 1661: ! 1662: case 10: /* HcBulkHeadED */ ! 1663: ohci->bulk_head = val & OHCI_EDPTR_MASK; ! 1664: break; ! 1665: ! 1666: case 11: /* HcBulkCurrentED */ ! 1667: ohci->bulk_cur = val & OHCI_EDPTR_MASK; ! 1668: break; ! 1669: ! 1670: case 13: /* HcFmInterval */ ! 1671: ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16; ! 1672: ohci->fit = (val & OHCI_FMI_FIT) >> 31; ! 1673: ohci_set_frame_interval(ohci, val); ! 1674: break; ! 1675: ! 1676: case 15: /* HcFmNumber */ ! 1677: break; ! 1678: ! 1679: case 16: /* HcPeriodicStart */ ! 1680: ohci->pstart = val & 0xffff; ! 1681: break; ! 1682: ! 1683: case 17: /* HcLSThreshold */ ! 1684: ohci->lst = val & 0xffff; ! 1685: break; ! 1686: ! 1687: case 18: /* HcRhDescriptorA */ ! 1688: ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK; ! 1689: ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK; ! 1690: break; ! 1691: ! 1692: case 19: /* HcRhDescriptorB */ ! 1693: break; ! 1694: ! 1695: case 20: /* HcRhStatus */ ! 1696: ohci_set_hub_status(ohci, val); ! 1697: break; ! 1698: ! 1699: /* PXA27x specific registers */ ! 1700: case 24: /* HcStatus */ ! 1701: ohci->hstatus &= ~(val & ohci->hmask); ! 1702: ! 1703: case 25: /* HcHReset */ ! 1704: ohci->hreset = val & ~OHCI_HRESET_FSBIR; ! 1705: if (val & OHCI_HRESET_FSBIR) ! 1706: ohci_reset(ohci); ! 1707: break; ! 1708: ! 1709: case 26: /* HcHInterruptEnable */ ! 1710: ohci->hmask = val; ! 1711: break; ! 1712: ! 1713: case 27: /* HcHInterruptTest */ ! 1714: ohci->htest = val; ! 1715: break; ! 1716: ! 1717: default: ! 1718: fprintf(stderr, "ohci_write: Bad offset %x\n", (int)addr); ! 1719: break; ! 1720: } ! 1721: } ! 1722: ! 1723: static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev) ! 1724: { ! 1725: if (ohci->async_td && ! 1726: usb_packet_is_inflight(&ohci->usb_packet) && ! 1727: ohci->usb_packet.ep->dev == dev) { ! 1728: usb_cancel_packet(&ohci->usb_packet); ! 1729: ohci->async_td = 0; ! 1730: } ! 1731: } ! 1732: ! 1733: static const MemoryRegionOps ohci_mem_ops = { ! 1734: .read = ohci_mem_read, ! 1735: .write = ohci_mem_write, ! 1736: .endianness = DEVICE_LITTLE_ENDIAN, ! 1737: }; ! 1738: ! 1739: static USBPortOps ohci_port_ops = { ! 1740: .attach = ohci_attach, ! 1741: .detach = ohci_detach, ! 1742: .child_detach = ohci_child_detach, ! 1743: .wakeup = ohci_wakeup, ! 1744: .complete = ohci_async_complete_packet, ! 1745: }; ! 1746: ! 1747: static USBBusOps ohci_bus_ops = { ! 1748: }; ! 1749: ! 1750: static int usb_ohci_init(OHCIState *ohci, DeviceState *dev, ! 1751: int num_ports, uint32_t localmem_base, ! 1752: char *masterbus, uint32_t firstport) ! 1753: { ! 1754: int i; ! 1755: ! 1756: if (usb_frame_time == 0) { ! 1757: #ifdef OHCI_TIME_WARP ! 1758: usb_frame_time = get_ticks_per_sec(); ! 1759: usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ/1000); ! 1760: #else ! 1761: usb_frame_time = muldiv64(1, get_ticks_per_sec(), 1000); ! 1762: if (get_ticks_per_sec() >= USB_HZ) { ! 1763: usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ); ! 1764: } else { ! 1765: usb_bit_time = 1; ! 1766: } ! 1767: #endif ! 1768: DPRINTF("usb-ohci: usb_bit_time=%" PRId64 " usb_frame_time=%" PRId64 "\n", ! 1769: usb_frame_time, usb_bit_time); ! 1770: } ! 1771: ! 1772: ohci->num_ports = num_ports; ! 1773: if (masterbus) { ! 1774: USBPort *ports[OHCI_MAX_PORTS]; ! 1775: for(i = 0; i < num_ports; i++) { ! 1776: ports[i] = &ohci->rhport[i].port; ! 1777: } ! 1778: if (usb_register_companion(masterbus, ports, num_ports, ! 1779: firstport, ohci, &ohci_port_ops, ! 1780: USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) { ! 1781: return -1; ! 1782: } ! 1783: } else { ! 1784: usb_bus_new(&ohci->bus, &ohci_bus_ops, dev); ! 1785: for (i = 0; i < num_ports; i++) { ! 1786: usb_register_port(&ohci->bus, &ohci->rhport[i].port, ! 1787: ohci, i, &ohci_port_ops, ! 1788: USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); ! 1789: } ! 1790: } ! 1791: ! 1792: memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256); ! 1793: ohci->localmem_base = localmem_base; ! 1794: ! 1795: ohci->name = object_get_typename(OBJECT(dev)); ! 1796: usb_packet_init(&ohci->usb_packet); ! 1797: ! 1798: ohci->async_td = 0; ! 1799: qemu_register_reset(ohci_reset, ohci); ! 1800: ! 1801: return 0; ! 1802: } ! 1803: ! 1804: typedef struct { ! 1805: PCIDevice pci_dev; ! 1806: OHCIState state; ! 1807: char *masterbus; ! 1808: uint32_t num_ports; ! 1809: uint32_t firstport; ! 1810: } OHCIPCIState; ! 1811: ! 1812: static int usb_ohci_initfn_pci(struct PCIDevice *dev) ! 1813: { ! 1814: OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev); ! 1815: ! 1816: ohci->pci_dev.config[PCI_CLASS_PROG] = 0x10; /* OHCI */ ! 1817: ohci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */ ! 1818: ! 1819: if (usb_ohci_init(&ohci->state, &dev->qdev, ohci->num_ports, 0, ! 1820: ohci->masterbus, ohci->firstport) != 0) { ! 1821: return -1; ! 1822: } ! 1823: ohci->state.irq = ohci->pci_dev.irq[0]; ! 1824: ! 1825: /* TODO: avoid cast below by using dev */ ! 1826: pci_register_bar(&ohci->pci_dev, 0, 0, &ohci->state.mem); ! 1827: return 0; ! 1828: } ! 1829: ! 1830: typedef struct { ! 1831: SysBusDevice busdev; ! 1832: OHCIState ohci; ! 1833: uint32_t num_ports; ! 1834: target_phys_addr_t dma_offset; ! 1835: } OHCISysBusState; ! 1836: ! 1837: static int ohci_init_pxa(SysBusDevice *dev) ! 1838: { ! 1839: OHCISysBusState *s = FROM_SYSBUS(OHCISysBusState, dev); ! 1840: ! 1841: /* Cannot fail as we pass NULL for masterbus */ ! 1842: usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0); ! 1843: sysbus_init_irq(dev, &s->ohci.irq); ! 1844: sysbus_init_mmio(dev, &s->ohci.mem); ! 1845: ! 1846: return 0; ! 1847: } ! 1848: ! 1849: static Property ohci_pci_properties[] = { ! 1850: DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus), ! 1851: DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3), ! 1852: DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0), ! 1853: DEFINE_PROP_END_OF_LIST(), ! 1854: }; ! 1855: ! 1856: static void ohci_pci_class_init(ObjectClass *klass, void *data) ! 1857: { ! 1858: DeviceClass *dc = DEVICE_CLASS(klass); ! 1859: PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ! 1860: ! 1861: k->init = usb_ohci_initfn_pci; ! 1862: k->vendor_id = PCI_VENDOR_ID_APPLE; ! 1863: k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB; ! 1864: k->class_id = PCI_CLASS_SERIAL_USB; ! 1865: dc->desc = "Apple USB Controller"; ! 1866: dc->props = ohci_pci_properties; ! 1867: } ! 1868: ! 1869: static TypeInfo ohci_pci_info = { ! 1870: .name = "pci-ohci", ! 1871: .parent = TYPE_PCI_DEVICE, ! 1872: .instance_size = sizeof(OHCIPCIState), ! 1873: .class_init = ohci_pci_class_init, ! 1874: }; ! 1875: ! 1876: static Property ohci_sysbus_properties[] = { ! 1877: DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3), ! 1878: DEFINE_PROP_TADDR("dma-offset", OHCISysBusState, dma_offset, 3), ! 1879: DEFINE_PROP_END_OF_LIST(), ! 1880: }; ! 1881: ! 1882: static void ohci_sysbus_class_init(ObjectClass *klass, void *data) ! 1883: { ! 1884: DeviceClass *dc = DEVICE_CLASS(klass); ! 1885: SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); ! 1886: ! 1887: sbc->init = ohci_init_pxa; ! 1888: dc->desc = "OHCI USB Controller"; ! 1889: dc->props = ohci_sysbus_properties; ! 1890: } ! 1891: ! 1892: static TypeInfo ohci_sysbus_info = { ! 1893: .name = "sysbus-ohci", ! 1894: .parent = TYPE_SYS_BUS_DEVICE, ! 1895: .instance_size = sizeof(OHCISysBusState), ! 1896: .class_init = ohci_sysbus_class_init, ! 1897: }; ! 1898: ! 1899: static void ohci_register_types(void) ! 1900: { ! 1901: type_register_static(&ohci_pci_info); ! 1902: type_register_static(&ohci_sysbus_info); ! 1903: } ! 1904: ! 1905: type_init(ohci_register_types)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.