|
|
1.1 ! root 1: /* ! 2: * QEMU USB EHCI Emulation ! 3: * ! 4: * Copyright(c) 2008 Emutex Ltd. (address@hidden) ! 5: * ! 6: * EHCI project was started by Mark Burkley, with contributions by ! 7: * Niels de Vos. David S. Ahern continued working on it. Kevin Wolf, ! 8: * Jan Kiszka and Vincent Palatin contributed bugfixes. ! 9: * ! 10: * ! 11: * This library is free software; you can redistribute it and/or ! 12: * modify it under the terms of the GNU Lesser General Public ! 13: * License as published by the Free Software Foundation; either ! 14: * version 2 of the License, or(at your option) any later version. ! 15: * ! 16: * This library is distributed in the hope that it will be useful, ! 17: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 18: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 19: * Lesser General Public License for more details. ! 20: * ! 21: * You should have received a copy of the GNU General Public License ! 22: * along with this program; if not, see <http://www.gnu.org/licenses/>. ! 23: */ ! 24: ! 25: #include "hw/hw.h" ! 26: #include "qemu-timer.h" ! 27: #include "hw/usb.h" ! 28: #include "hw/pci.h" ! 29: #include "monitor.h" ! 30: #include "trace.h" ! 31: #include "dma.h" ! 32: ! 33: #define EHCI_DEBUG 0 ! 34: ! 35: #if EHCI_DEBUG ! 36: #define DPRINTF printf ! 37: #else ! 38: #define DPRINTF(...) ! 39: #endif ! 40: ! 41: /* internal processing - reset HC to try and recover */ ! 42: #define USB_RET_PROCERR (-99) ! 43: ! 44: #define MMIO_SIZE 0x1000 ! 45: ! 46: /* Capability Registers Base Address - section 2.2 */ ! 47: #define CAPREGBASE 0x0000 ! 48: #define CAPLENGTH CAPREGBASE + 0x0000 // 1-byte, 0x0001 reserved ! 49: #define HCIVERSION CAPREGBASE + 0x0002 // 2-bytes, i/f version # ! 50: #define HCSPARAMS CAPREGBASE + 0x0004 // 4-bytes, structural params ! 51: #define HCCPARAMS CAPREGBASE + 0x0008 // 4-bytes, capability params ! 52: #define EECP HCCPARAMS + 1 ! 53: #define HCSPPORTROUTE1 CAPREGBASE + 0x000c ! 54: #define HCSPPORTROUTE2 CAPREGBASE + 0x0010 ! 55: ! 56: #define OPREGBASE 0x0020 // Operational Registers Base Address ! 57: ! 58: #define USBCMD OPREGBASE + 0x0000 ! 59: #define USBCMD_RUNSTOP (1 << 0) // run / Stop ! 60: #define USBCMD_HCRESET (1 << 1) // HC Reset ! 61: #define USBCMD_FLS (3 << 2) // Frame List Size ! 62: #define USBCMD_FLS_SH 2 // Frame List Size Shift ! 63: #define USBCMD_PSE (1 << 4) // Periodic Schedule Enable ! 64: #define USBCMD_ASE (1 << 5) // Asynch Schedule Enable ! 65: #define USBCMD_IAAD (1 << 6) // Int Asynch Advance Doorbell ! 66: #define USBCMD_LHCR (1 << 7) // Light Host Controller Reset ! 67: #define USBCMD_ASPMC (3 << 8) // Async Sched Park Mode Count ! 68: #define USBCMD_ASPME (1 << 11) // Async Sched Park Mode Enable ! 69: #define USBCMD_ITC (0x7f << 16) // Int Threshold Control ! 70: #define USBCMD_ITC_SH 16 // Int Threshold Control Shift ! 71: ! 72: #define USBSTS OPREGBASE + 0x0004 ! 73: #define USBSTS_RO_MASK 0x0000003f ! 74: #define USBSTS_INT (1 << 0) // USB Interrupt ! 75: #define USBSTS_ERRINT (1 << 1) // Error Interrupt ! 76: #define USBSTS_PCD (1 << 2) // Port Change Detect ! 77: #define USBSTS_FLR (1 << 3) // Frame List Rollover ! 78: #define USBSTS_HSE (1 << 4) // Host System Error ! 79: #define USBSTS_IAA (1 << 5) // Interrupt on Async Advance ! 80: #define USBSTS_HALT (1 << 12) // HC Halted ! 81: #define USBSTS_REC (1 << 13) // Reclamation ! 82: #define USBSTS_PSS (1 << 14) // Periodic Schedule Status ! 83: #define USBSTS_ASS (1 << 15) // Asynchronous Schedule Status ! 84: ! 85: /* ! 86: * Interrupt enable bits correspond to the interrupt active bits in USBSTS ! 87: * so no need to redefine here. ! 88: */ ! 89: #define USBINTR OPREGBASE + 0x0008 ! 90: #define USBINTR_MASK 0x0000003f ! 91: ! 92: #define FRINDEX OPREGBASE + 0x000c ! 93: #define CTRLDSSEGMENT OPREGBASE + 0x0010 ! 94: #define PERIODICLISTBASE OPREGBASE + 0x0014 ! 95: #define ASYNCLISTADDR OPREGBASE + 0x0018 ! 96: #define ASYNCLISTADDR_MASK 0xffffffe0 ! 97: ! 98: #define CONFIGFLAG OPREGBASE + 0x0040 ! 99: ! 100: #define PORTSC (OPREGBASE + 0x0044) ! 101: #define PORTSC_BEGIN PORTSC ! 102: #define PORTSC_END (PORTSC + 4 * NB_PORTS) ! 103: /* ! 104: * Bits that are reserved or are read-only are masked out of values ! 105: * written to us by software ! 106: */ ! 107: #define PORTSC_RO_MASK 0x007001c0 ! 108: #define PORTSC_RWC_MASK 0x0000002a ! 109: #define PORTSC_WKOC_E (1 << 22) // Wake on Over Current Enable ! 110: #define PORTSC_WKDS_E (1 << 21) // Wake on Disconnect Enable ! 111: #define PORTSC_WKCN_E (1 << 20) // Wake on Connect Enable ! 112: #define PORTSC_PTC (15 << 16) // Port Test Control ! 113: #define PORTSC_PTC_SH 16 // Port Test Control shift ! 114: #define PORTSC_PIC (3 << 14) // Port Indicator Control ! 115: #define PORTSC_PIC_SH 14 // Port Indicator Control Shift ! 116: #define PORTSC_POWNER (1 << 13) // Port Owner ! 117: #define PORTSC_PPOWER (1 << 12) // Port Power ! 118: #define PORTSC_LINESTAT (3 << 10) // Port Line Status ! 119: #define PORTSC_LINESTAT_SH 10 // Port Line Status Shift ! 120: #define PORTSC_PRESET (1 << 8) // Port Reset ! 121: #define PORTSC_SUSPEND (1 << 7) // Port Suspend ! 122: #define PORTSC_FPRES (1 << 6) // Force Port Resume ! 123: #define PORTSC_OCC (1 << 5) // Over Current Change ! 124: #define PORTSC_OCA (1 << 4) // Over Current Active ! 125: #define PORTSC_PEDC (1 << 3) // Port Enable/Disable Change ! 126: #define PORTSC_PED (1 << 2) // Port Enable/Disable ! 127: #define PORTSC_CSC (1 << 1) // Connect Status Change ! 128: #define PORTSC_CONNECT (1 << 0) // Current Connect Status ! 129: ! 130: #define FRAME_TIMER_FREQ 1000 ! 131: #define FRAME_TIMER_NS (1000000000 / FRAME_TIMER_FREQ) ! 132: ! 133: #define NB_MAXINTRATE 8 // Max rate at which controller issues ints ! 134: #define NB_PORTS 6 // Number of downstream ports ! 135: #define BUFF_SIZE 5*4096 // Max bytes to transfer per transaction ! 136: #define MAX_QH 100 // Max allowable queue heads in a chain ! 137: ! 138: /* Internal periodic / asynchronous schedule state machine states ! 139: */ ! 140: typedef enum { ! 141: EST_INACTIVE = 1000, ! 142: EST_ACTIVE, ! 143: EST_EXECUTING, ! 144: EST_SLEEPING, ! 145: /* The following states are internal to the state machine function ! 146: */ ! 147: EST_WAITLISTHEAD, ! 148: EST_FETCHENTRY, ! 149: EST_FETCHQH, ! 150: EST_FETCHITD, ! 151: EST_FETCHSITD, ! 152: EST_ADVANCEQUEUE, ! 153: EST_FETCHQTD, ! 154: EST_EXECUTE, ! 155: EST_WRITEBACK, ! 156: EST_HORIZONTALQH ! 157: } EHCI_STATES; ! 158: ! 159: /* macros for accessing fields within next link pointer entry */ ! 160: #define NLPTR_GET(x) ((x) & 0xffffffe0) ! 161: #define NLPTR_TYPE_GET(x) (((x) >> 1) & 3) ! 162: #define NLPTR_TBIT(x) ((x) & 1) // 1=invalid, 0=valid ! 163: ! 164: /* link pointer types */ ! 165: #define NLPTR_TYPE_ITD 0 // isoc xfer descriptor ! 166: #define NLPTR_TYPE_QH 1 // queue head ! 167: #define NLPTR_TYPE_STITD 2 // split xaction, isoc xfer descriptor ! 168: #define NLPTR_TYPE_FSTN 3 // frame span traversal node ! 169: ! 170: ! 171: /* EHCI spec version 1.0 Section 3.3 ! 172: */ ! 173: typedef struct EHCIitd { ! 174: uint32_t next; ! 175: ! 176: uint32_t transact[8]; ! 177: #define ITD_XACT_ACTIVE (1 << 31) ! 178: #define ITD_XACT_DBERROR (1 << 30) ! 179: #define ITD_XACT_BABBLE (1 << 29) ! 180: #define ITD_XACT_XACTERR (1 << 28) ! 181: #define ITD_XACT_LENGTH_MASK 0x0fff0000 ! 182: #define ITD_XACT_LENGTH_SH 16 ! 183: #define ITD_XACT_IOC (1 << 15) ! 184: #define ITD_XACT_PGSEL_MASK 0x00007000 ! 185: #define ITD_XACT_PGSEL_SH 12 ! 186: #define ITD_XACT_OFFSET_MASK 0x00000fff ! 187: ! 188: uint32_t bufptr[7]; ! 189: #define ITD_BUFPTR_MASK 0xfffff000 ! 190: #define ITD_BUFPTR_SH 12 ! 191: #define ITD_BUFPTR_EP_MASK 0x00000f00 ! 192: #define ITD_BUFPTR_EP_SH 8 ! 193: #define ITD_BUFPTR_DEVADDR_MASK 0x0000007f ! 194: #define ITD_BUFPTR_DEVADDR_SH 0 ! 195: #define ITD_BUFPTR_DIRECTION (1 << 11) ! 196: #define ITD_BUFPTR_MAXPKT_MASK 0x000007ff ! 197: #define ITD_BUFPTR_MAXPKT_SH 0 ! 198: #define ITD_BUFPTR_MULT_MASK 0x00000003 ! 199: #define ITD_BUFPTR_MULT_SH 0 ! 200: } EHCIitd; ! 201: ! 202: /* EHCI spec version 1.0 Section 3.4 ! 203: */ ! 204: typedef struct EHCIsitd { ! 205: uint32_t next; // Standard next link pointer ! 206: uint32_t epchar; ! 207: #define SITD_EPCHAR_IO (1 << 31) ! 208: #define SITD_EPCHAR_PORTNUM_MASK 0x7f000000 ! 209: #define SITD_EPCHAR_PORTNUM_SH 24 ! 210: #define SITD_EPCHAR_HUBADD_MASK 0x007f0000 ! 211: #define SITD_EPCHAR_HUBADDR_SH 16 ! 212: #define SITD_EPCHAR_EPNUM_MASK 0x00000f00 ! 213: #define SITD_EPCHAR_EPNUM_SH 8 ! 214: #define SITD_EPCHAR_DEVADDR_MASK 0x0000007f ! 215: ! 216: uint32_t uframe; ! 217: #define SITD_UFRAME_CMASK_MASK 0x0000ff00 ! 218: #define SITD_UFRAME_CMASK_SH 8 ! 219: #define SITD_UFRAME_SMASK_MASK 0x000000ff ! 220: ! 221: uint32_t results; ! 222: #define SITD_RESULTS_IOC (1 << 31) ! 223: #define SITD_RESULTS_PGSEL (1 << 30) ! 224: #define SITD_RESULTS_TBYTES_MASK 0x03ff0000 ! 225: #define SITD_RESULTS_TYBYTES_SH 16 ! 226: #define SITD_RESULTS_CPROGMASK_MASK 0x0000ff00 ! 227: #define SITD_RESULTS_CPROGMASK_SH 8 ! 228: #define SITD_RESULTS_ACTIVE (1 << 7) ! 229: #define SITD_RESULTS_ERR (1 << 6) ! 230: #define SITD_RESULTS_DBERR (1 << 5) ! 231: #define SITD_RESULTS_BABBLE (1 << 4) ! 232: #define SITD_RESULTS_XACTERR (1 << 3) ! 233: #define SITD_RESULTS_MISSEDUF (1 << 2) ! 234: #define SITD_RESULTS_SPLITXSTATE (1 << 1) ! 235: ! 236: uint32_t bufptr[2]; ! 237: #define SITD_BUFPTR_MASK 0xfffff000 ! 238: #define SITD_BUFPTR_CURROFF_MASK 0x00000fff ! 239: #define SITD_BUFPTR_TPOS_MASK 0x00000018 ! 240: #define SITD_BUFPTR_TPOS_SH 3 ! 241: #define SITD_BUFPTR_TCNT_MASK 0x00000007 ! 242: ! 243: uint32_t backptr; // Standard next link pointer ! 244: } EHCIsitd; ! 245: ! 246: /* EHCI spec version 1.0 Section 3.5 ! 247: */ ! 248: typedef struct EHCIqtd { ! 249: uint32_t next; // Standard next link pointer ! 250: uint32_t altnext; // Standard next link pointer ! 251: uint32_t token; ! 252: #define QTD_TOKEN_DTOGGLE (1 << 31) ! 253: #define QTD_TOKEN_TBYTES_MASK 0x7fff0000 ! 254: #define QTD_TOKEN_TBYTES_SH 16 ! 255: #define QTD_TOKEN_IOC (1 << 15) ! 256: #define QTD_TOKEN_CPAGE_MASK 0x00007000 ! 257: #define QTD_TOKEN_CPAGE_SH 12 ! 258: #define QTD_TOKEN_CERR_MASK 0x00000c00 ! 259: #define QTD_TOKEN_CERR_SH 10 ! 260: #define QTD_TOKEN_PID_MASK 0x00000300 ! 261: #define QTD_TOKEN_PID_SH 8 ! 262: #define QTD_TOKEN_ACTIVE (1 << 7) ! 263: #define QTD_TOKEN_HALT (1 << 6) ! 264: #define QTD_TOKEN_DBERR (1 << 5) ! 265: #define QTD_TOKEN_BABBLE (1 << 4) ! 266: #define QTD_TOKEN_XACTERR (1 << 3) ! 267: #define QTD_TOKEN_MISSEDUF (1 << 2) ! 268: #define QTD_TOKEN_SPLITXSTATE (1 << 1) ! 269: #define QTD_TOKEN_PING (1 << 0) ! 270: ! 271: uint32_t bufptr[5]; // Standard buffer pointer ! 272: #define QTD_BUFPTR_MASK 0xfffff000 ! 273: #define QTD_BUFPTR_SH 12 ! 274: } EHCIqtd; ! 275: ! 276: /* EHCI spec version 1.0 Section 3.6 ! 277: */ ! 278: typedef struct EHCIqh { ! 279: uint32_t next; // Standard next link pointer ! 280: ! 281: /* endpoint characteristics */ ! 282: uint32_t epchar; ! 283: #define QH_EPCHAR_RL_MASK 0xf0000000 ! 284: #define QH_EPCHAR_RL_SH 28 ! 285: #define QH_EPCHAR_C (1 << 27) ! 286: #define QH_EPCHAR_MPLEN_MASK 0x07FF0000 ! 287: #define QH_EPCHAR_MPLEN_SH 16 ! 288: #define QH_EPCHAR_H (1 << 15) ! 289: #define QH_EPCHAR_DTC (1 << 14) ! 290: #define QH_EPCHAR_EPS_MASK 0x00003000 ! 291: #define QH_EPCHAR_EPS_SH 12 ! 292: #define EHCI_QH_EPS_FULL 0 ! 293: #define EHCI_QH_EPS_LOW 1 ! 294: #define EHCI_QH_EPS_HIGH 2 ! 295: #define EHCI_QH_EPS_RESERVED 3 ! 296: ! 297: #define QH_EPCHAR_EP_MASK 0x00000f00 ! 298: #define QH_EPCHAR_EP_SH 8 ! 299: #define QH_EPCHAR_I (1 << 7) ! 300: #define QH_EPCHAR_DEVADDR_MASK 0x0000007f ! 301: #define QH_EPCHAR_DEVADDR_SH 0 ! 302: ! 303: /* endpoint capabilities */ ! 304: uint32_t epcap; ! 305: #define QH_EPCAP_MULT_MASK 0xc0000000 ! 306: #define QH_EPCAP_MULT_SH 30 ! 307: #define QH_EPCAP_PORTNUM_MASK 0x3f800000 ! 308: #define QH_EPCAP_PORTNUM_SH 23 ! 309: #define QH_EPCAP_HUBADDR_MASK 0x007f0000 ! 310: #define QH_EPCAP_HUBADDR_SH 16 ! 311: #define QH_EPCAP_CMASK_MASK 0x0000ff00 ! 312: #define QH_EPCAP_CMASK_SH 8 ! 313: #define QH_EPCAP_SMASK_MASK 0x000000ff ! 314: #define QH_EPCAP_SMASK_SH 0 ! 315: ! 316: uint32_t current_qtd; // Standard next link pointer ! 317: uint32_t next_qtd; // Standard next link pointer ! 318: uint32_t altnext_qtd; ! 319: #define QH_ALTNEXT_NAKCNT_MASK 0x0000001e ! 320: #define QH_ALTNEXT_NAKCNT_SH 1 ! 321: ! 322: uint32_t token; // Same as QTD token ! 323: uint32_t bufptr[5]; // Standard buffer pointer ! 324: #define BUFPTR_CPROGMASK_MASK 0x000000ff ! 325: #define BUFPTR_FRAMETAG_MASK 0x0000001f ! 326: #define BUFPTR_SBYTES_MASK 0x00000fe0 ! 327: #define BUFPTR_SBYTES_SH 5 ! 328: } EHCIqh; ! 329: ! 330: /* EHCI spec version 1.0 Section 3.7 ! 331: */ ! 332: typedef struct EHCIfstn { ! 333: uint32_t next; // Standard next link pointer ! 334: uint32_t backptr; // Standard next link pointer ! 335: } EHCIfstn; ! 336: ! 337: typedef struct EHCIQueue EHCIQueue; ! 338: typedef struct EHCIState EHCIState; ! 339: ! 340: enum async_state { ! 341: EHCI_ASYNC_NONE = 0, ! 342: EHCI_ASYNC_INFLIGHT, ! 343: EHCI_ASYNC_FINISHED, ! 344: }; ! 345: ! 346: struct EHCIQueue { ! 347: EHCIState *ehci; ! 348: QTAILQ_ENTRY(EHCIQueue) next; ! 349: uint32_t seen; ! 350: uint64_t ts; ! 351: ! 352: /* cached data from guest - needs to be flushed ! 353: * when guest removes an entry (doorbell, handshake sequence) ! 354: */ ! 355: EHCIqh qh; // copy of current QH (being worked on) ! 356: uint32_t qhaddr; // address QH read from ! 357: EHCIqtd qtd; // copy of current QTD (being worked on) ! 358: uint32_t qtdaddr; // address QTD read from ! 359: ! 360: USBPacket packet; ! 361: QEMUSGList sgl; ! 362: int pid; ! 363: uint32_t tbytes; ! 364: enum async_state async; ! 365: int usb_status; ! 366: }; ! 367: ! 368: typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead; ! 369: ! 370: struct EHCIState { ! 371: PCIDevice dev; ! 372: USBBus bus; ! 373: qemu_irq irq; ! 374: MemoryRegion mem; ! 375: int companion_count; ! 376: ! 377: /* properties */ ! 378: uint32_t freq; ! 379: uint32_t maxframes; ! 380: ! 381: /* ! 382: * EHCI spec version 1.0 Section 2.3 ! 383: * Host Controller Operational Registers ! 384: */ ! 385: union { ! 386: uint8_t mmio[MMIO_SIZE]; ! 387: struct { ! 388: uint8_t cap[OPREGBASE]; ! 389: uint32_t usbcmd; ! 390: uint32_t usbsts; ! 391: uint32_t usbintr; ! 392: uint32_t frindex; ! 393: uint32_t ctrldssegment; ! 394: uint32_t periodiclistbase; ! 395: uint32_t asynclistaddr; ! 396: uint32_t notused[9]; ! 397: uint32_t configflag; ! 398: uint32_t portsc[NB_PORTS]; ! 399: }; ! 400: }; ! 401: ! 402: /* ! 403: * Internal states, shadow registers, etc ! 404: */ ! 405: QEMUTimer *frame_timer; ! 406: int attach_poll_counter; ! 407: int astate; // Current state in asynchronous schedule ! 408: int pstate; // Current state in periodic schedule ! 409: USBPort ports[NB_PORTS]; ! 410: USBPort *companion_ports[NB_PORTS]; ! 411: uint32_t usbsts_pending; ! 412: EHCIQueueHead aqueues; ! 413: EHCIQueueHead pqueues; ! 414: ! 415: uint32_t a_fetch_addr; // which address to look at next ! 416: uint32_t p_fetch_addr; // which address to look at next ! 417: ! 418: USBPacket ipacket; ! 419: QEMUSGList isgl; ! 420: ! 421: uint64_t last_run_ns; ! 422: }; ! 423: ! 424: #define SET_LAST_RUN_CLOCK(s) \ ! 425: (s)->last_run_ns = qemu_get_clock_ns(vm_clock); ! 426: ! 427: /* nifty macros from Arnon's EHCI version */ ! 428: #define get_field(data, field) \ ! 429: (((data) & field##_MASK) >> field##_SH) ! 430: ! 431: #define set_field(data, newval, field) do { \ ! 432: uint32_t val = *data; \ ! 433: val &= ~ field##_MASK; \ ! 434: val |= ((newval) << field##_SH) & field##_MASK; \ ! 435: *data = val; \ ! 436: } while(0) ! 437: ! 438: static const char *ehci_state_names[] = { ! 439: [EST_INACTIVE] = "INACTIVE", ! 440: [EST_ACTIVE] = "ACTIVE", ! 441: [EST_EXECUTING] = "EXECUTING", ! 442: [EST_SLEEPING] = "SLEEPING", ! 443: [EST_WAITLISTHEAD] = "WAITLISTHEAD", ! 444: [EST_FETCHENTRY] = "FETCH ENTRY", ! 445: [EST_FETCHQH] = "FETCH QH", ! 446: [EST_FETCHITD] = "FETCH ITD", ! 447: [EST_ADVANCEQUEUE] = "ADVANCEQUEUE", ! 448: [EST_FETCHQTD] = "FETCH QTD", ! 449: [EST_EXECUTE] = "EXECUTE", ! 450: [EST_WRITEBACK] = "WRITEBACK", ! 451: [EST_HORIZONTALQH] = "HORIZONTALQH", ! 452: }; ! 453: ! 454: static const char *ehci_mmio_names[] = { ! 455: [CAPLENGTH] = "CAPLENGTH", ! 456: [HCIVERSION] = "HCIVERSION", ! 457: [HCSPARAMS] = "HCSPARAMS", ! 458: [HCCPARAMS] = "HCCPARAMS", ! 459: [USBCMD] = "USBCMD", ! 460: [USBSTS] = "USBSTS", ! 461: [USBINTR] = "USBINTR", ! 462: [FRINDEX] = "FRINDEX", ! 463: [PERIODICLISTBASE] = "P-LIST BASE", ! 464: [ASYNCLISTADDR] = "A-LIST ADDR", ! 465: [PORTSC_BEGIN] = "PORTSC #0", ! 466: [PORTSC_BEGIN + 4] = "PORTSC #1", ! 467: [PORTSC_BEGIN + 8] = "PORTSC #2", ! 468: [PORTSC_BEGIN + 12] = "PORTSC #3", ! 469: [PORTSC_BEGIN + 16] = "PORTSC #4", ! 470: [PORTSC_BEGIN + 20] = "PORTSC #5", ! 471: [CONFIGFLAG] = "CONFIGFLAG", ! 472: }; ! 473: ! 474: static const char *nr2str(const char **n, size_t len, uint32_t nr) ! 475: { ! 476: if (nr < len && n[nr] != NULL) { ! 477: return n[nr]; ! 478: } else { ! 479: return "unknown"; ! 480: } ! 481: } ! 482: ! 483: static const char *state2str(uint32_t state) ! 484: { ! 485: return nr2str(ehci_state_names, ARRAY_SIZE(ehci_state_names), state); ! 486: } ! 487: ! 488: static const char *addr2str(target_phys_addr_t addr) ! 489: { ! 490: return nr2str(ehci_mmio_names, ARRAY_SIZE(ehci_mmio_names), addr); ! 491: } ! 492: ! 493: static void ehci_trace_usbsts(uint32_t mask, int state) ! 494: { ! 495: /* interrupts */ ! 496: if (mask & USBSTS_INT) { ! 497: trace_usb_ehci_usbsts("INT", state); ! 498: } ! 499: if (mask & USBSTS_ERRINT) { ! 500: trace_usb_ehci_usbsts("ERRINT", state); ! 501: } ! 502: if (mask & USBSTS_PCD) { ! 503: trace_usb_ehci_usbsts("PCD", state); ! 504: } ! 505: if (mask & USBSTS_FLR) { ! 506: trace_usb_ehci_usbsts("FLR", state); ! 507: } ! 508: if (mask & USBSTS_HSE) { ! 509: trace_usb_ehci_usbsts("HSE", state); ! 510: } ! 511: if (mask & USBSTS_IAA) { ! 512: trace_usb_ehci_usbsts("IAA", state); ! 513: } ! 514: ! 515: /* status */ ! 516: if (mask & USBSTS_HALT) { ! 517: trace_usb_ehci_usbsts("HALT", state); ! 518: } ! 519: if (mask & USBSTS_REC) { ! 520: trace_usb_ehci_usbsts("REC", state); ! 521: } ! 522: if (mask & USBSTS_PSS) { ! 523: trace_usb_ehci_usbsts("PSS", state); ! 524: } ! 525: if (mask & USBSTS_ASS) { ! 526: trace_usb_ehci_usbsts("ASS", state); ! 527: } ! 528: } ! 529: ! 530: static inline void ehci_set_usbsts(EHCIState *s, int mask) ! 531: { ! 532: if ((s->usbsts & mask) == mask) { ! 533: return; ! 534: } ! 535: ehci_trace_usbsts(mask, 1); ! 536: s->usbsts |= mask; ! 537: } ! 538: ! 539: static inline void ehci_clear_usbsts(EHCIState *s, int mask) ! 540: { ! 541: if ((s->usbsts & mask) == 0) { ! 542: return; ! 543: } ! 544: ehci_trace_usbsts(mask, 0); ! 545: s->usbsts &= ~mask; ! 546: } ! 547: ! 548: static inline void ehci_set_interrupt(EHCIState *s, int intr) ! 549: { ! 550: int level = 0; ! 551: ! 552: // TODO honour interrupt threshold requests ! 553: ! 554: ehci_set_usbsts(s, intr); ! 555: ! 556: if ((s->usbsts & USBINTR_MASK) & s->usbintr) { ! 557: level = 1; ! 558: } ! 559: ! 560: qemu_set_irq(s->irq, level); ! 561: } ! 562: ! 563: static inline void ehci_record_interrupt(EHCIState *s, int intr) ! 564: { ! 565: s->usbsts_pending |= intr; ! 566: } ! 567: ! 568: static inline void ehci_commit_interrupt(EHCIState *s) ! 569: { ! 570: if (!s->usbsts_pending) { ! 571: return; ! 572: } ! 573: ehci_set_interrupt(s, s->usbsts_pending); ! 574: s->usbsts_pending = 0; ! 575: } ! 576: ! 577: static void ehci_set_state(EHCIState *s, int async, int state) ! 578: { ! 579: if (async) { ! 580: trace_usb_ehci_state("async", state2str(state)); ! 581: s->astate = state; ! 582: } else { ! 583: trace_usb_ehci_state("periodic", state2str(state)); ! 584: s->pstate = state; ! 585: } ! 586: } ! 587: ! 588: static int ehci_get_state(EHCIState *s, int async) ! 589: { ! 590: return async ? s->astate : s->pstate; ! 591: } ! 592: ! 593: static void ehci_set_fetch_addr(EHCIState *s, int async, uint32_t addr) ! 594: { ! 595: if (async) { ! 596: s->a_fetch_addr = addr; ! 597: } else { ! 598: s->p_fetch_addr = addr; ! 599: } ! 600: } ! 601: ! 602: static int ehci_get_fetch_addr(EHCIState *s, int async) ! 603: { ! 604: return async ? s->a_fetch_addr : s->p_fetch_addr; ! 605: } ! 606: ! 607: static void ehci_trace_qh(EHCIQueue *q, target_phys_addr_t addr, EHCIqh *qh) ! 608: { ! 609: /* need three here due to argument count limits */ ! 610: trace_usb_ehci_qh_ptrs(q, addr, qh->next, ! 611: qh->current_qtd, qh->next_qtd, qh->altnext_qtd); ! 612: trace_usb_ehci_qh_fields(addr, ! 613: get_field(qh->epchar, QH_EPCHAR_RL), ! 614: get_field(qh->epchar, QH_EPCHAR_MPLEN), ! 615: get_field(qh->epchar, QH_EPCHAR_EPS), ! 616: get_field(qh->epchar, QH_EPCHAR_EP), ! 617: get_field(qh->epchar, QH_EPCHAR_DEVADDR)); ! 618: trace_usb_ehci_qh_bits(addr, ! 619: (bool)(qh->epchar & QH_EPCHAR_C), ! 620: (bool)(qh->epchar & QH_EPCHAR_H), ! 621: (bool)(qh->epchar & QH_EPCHAR_DTC), ! 622: (bool)(qh->epchar & QH_EPCHAR_I)); ! 623: } ! 624: ! 625: static void ehci_trace_qtd(EHCIQueue *q, target_phys_addr_t addr, EHCIqtd *qtd) ! 626: { ! 627: /* need three here due to argument count limits */ ! 628: trace_usb_ehci_qtd_ptrs(q, addr, qtd->next, qtd->altnext); ! 629: trace_usb_ehci_qtd_fields(addr, ! 630: get_field(qtd->token, QTD_TOKEN_TBYTES), ! 631: get_field(qtd->token, QTD_TOKEN_CPAGE), ! 632: get_field(qtd->token, QTD_TOKEN_CERR), ! 633: get_field(qtd->token, QTD_TOKEN_PID)); ! 634: trace_usb_ehci_qtd_bits(addr, ! 635: (bool)(qtd->token & QTD_TOKEN_IOC), ! 636: (bool)(qtd->token & QTD_TOKEN_ACTIVE), ! 637: (bool)(qtd->token & QTD_TOKEN_HALT), ! 638: (bool)(qtd->token & QTD_TOKEN_BABBLE), ! 639: (bool)(qtd->token & QTD_TOKEN_XACTERR)); ! 640: } ! 641: ! 642: static void ehci_trace_itd(EHCIState *s, target_phys_addr_t addr, EHCIitd *itd) ! 643: { ! 644: trace_usb_ehci_itd(addr, itd->next, ! 645: get_field(itd->bufptr[1], ITD_BUFPTR_MAXPKT), ! 646: get_field(itd->bufptr[2], ITD_BUFPTR_MULT), ! 647: get_field(itd->bufptr[0], ITD_BUFPTR_EP), ! 648: get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR)); ! 649: } ! 650: ! 651: static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr, ! 652: EHCIsitd *sitd) ! 653: { ! 654: trace_usb_ehci_sitd(addr, sitd->next, ! 655: (bool)(sitd->results & SITD_RESULTS_ACTIVE)); ! 656: } ! 657: ! 658: /* queue management */ ! 659: ! 660: static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async) ! 661: { ! 662: EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; ! 663: EHCIQueue *q; ! 664: ! 665: q = g_malloc0(sizeof(*q)); ! 666: q->ehci = ehci; ! 667: usb_packet_init(&q->packet); ! 668: QTAILQ_INSERT_HEAD(head, q, next); ! 669: trace_usb_ehci_queue_action(q, "alloc"); ! 670: return q; ! 671: } ! 672: ! 673: static void ehci_free_queue(EHCIQueue *q, int async) ! 674: { ! 675: EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues; ! 676: trace_usb_ehci_queue_action(q, "free"); ! 677: if (q->async == EHCI_ASYNC_INFLIGHT) { ! 678: usb_cancel_packet(&q->packet); ! 679: } ! 680: QTAILQ_REMOVE(head, q, next); ! 681: g_free(q); ! 682: } ! 683: ! 684: static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr, ! 685: int async) ! 686: { ! 687: EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; ! 688: EHCIQueue *q; ! 689: ! 690: QTAILQ_FOREACH(q, head, next) { ! 691: if (addr == q->qhaddr) { ! 692: return q; ! 693: } ! 694: } ! 695: return NULL; ! 696: } ! 697: ! 698: static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush) ! 699: { ! 700: EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; ! 701: EHCIQueue *q, *tmp; ! 702: ! 703: QTAILQ_FOREACH_SAFE(q, head, next, tmp) { ! 704: if (q->seen) { ! 705: q->seen = 0; ! 706: q->ts = ehci->last_run_ns; ! 707: continue; ! 708: } ! 709: if (!flush && ehci->last_run_ns < q->ts + 250000000) { ! 710: /* allow 0.25 sec idle */ ! 711: continue; ! 712: } ! 713: ehci_free_queue(q, async); ! 714: } ! 715: } ! 716: ! 717: static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async) ! 718: { ! 719: EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; ! 720: EHCIQueue *q, *tmp; ! 721: ! 722: QTAILQ_FOREACH_SAFE(q, head, next, tmp) { ! 723: if (!usb_packet_is_inflight(&q->packet) || ! 724: q->packet.ep->dev != dev) { ! 725: continue; ! 726: } ! 727: ehci_free_queue(q, async); ! 728: } ! 729: } ! 730: ! 731: static void ehci_queues_rip_all(EHCIState *ehci, int async) ! 732: { ! 733: EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; ! 734: EHCIQueue *q, *tmp; ! 735: ! 736: QTAILQ_FOREACH_SAFE(q, head, next, tmp) { ! 737: ehci_free_queue(q, async); ! 738: } ! 739: } ! 740: ! 741: /* Attach or detach a device on root hub */ ! 742: ! 743: static void ehci_attach(USBPort *port) ! 744: { ! 745: EHCIState *s = port->opaque; ! 746: uint32_t *portsc = &s->portsc[port->index]; ! 747: ! 748: trace_usb_ehci_port_attach(port->index, port->dev->product_desc); ! 749: ! 750: if (*portsc & PORTSC_POWNER) { ! 751: USBPort *companion = s->companion_ports[port->index]; ! 752: companion->dev = port->dev; ! 753: companion->ops->attach(companion); ! 754: return; ! 755: } ! 756: ! 757: *portsc |= PORTSC_CONNECT; ! 758: *portsc |= PORTSC_CSC; ! 759: ! 760: ehci_set_interrupt(s, USBSTS_PCD); ! 761: } ! 762: ! 763: static void ehci_detach(USBPort *port) ! 764: { ! 765: EHCIState *s = port->opaque; ! 766: uint32_t *portsc = &s->portsc[port->index]; ! 767: ! 768: trace_usb_ehci_port_detach(port->index); ! 769: ! 770: if (*portsc & PORTSC_POWNER) { ! 771: USBPort *companion = s->companion_ports[port->index]; ! 772: companion->ops->detach(companion); ! 773: companion->dev = NULL; ! 774: /* ! 775: * EHCI spec 4.2.2: "When a disconnect occurs... On the event, ! 776: * the port ownership is returned immediately to the EHCI controller." ! 777: */ ! 778: *portsc &= ~PORTSC_POWNER; ! 779: return; ! 780: } ! 781: ! 782: ehci_queues_rip_device(s, port->dev, 0); ! 783: ehci_queues_rip_device(s, port->dev, 1); ! 784: ! 785: *portsc &= ~(PORTSC_CONNECT|PORTSC_PED); ! 786: *portsc |= PORTSC_CSC; ! 787: ! 788: ehci_set_interrupt(s, USBSTS_PCD); ! 789: } ! 790: ! 791: static void ehci_child_detach(USBPort *port, USBDevice *child) ! 792: { ! 793: EHCIState *s = port->opaque; ! 794: uint32_t portsc = s->portsc[port->index]; ! 795: ! 796: if (portsc & PORTSC_POWNER) { ! 797: USBPort *companion = s->companion_ports[port->index]; ! 798: companion->ops->child_detach(companion, child); ! 799: return; ! 800: } ! 801: ! 802: ehci_queues_rip_device(s, child, 0); ! 803: ehci_queues_rip_device(s, child, 1); ! 804: } ! 805: ! 806: static void ehci_wakeup(USBPort *port) ! 807: { ! 808: EHCIState *s = port->opaque; ! 809: uint32_t portsc = s->portsc[port->index]; ! 810: ! 811: if (portsc & PORTSC_POWNER) { ! 812: USBPort *companion = s->companion_ports[port->index]; ! 813: if (companion->ops->wakeup) { ! 814: companion->ops->wakeup(companion); ! 815: } ! 816: } ! 817: } ! 818: ! 819: static int ehci_register_companion(USBBus *bus, USBPort *ports[], ! 820: uint32_t portcount, uint32_t firstport) ! 821: { ! 822: EHCIState *s = container_of(bus, EHCIState, bus); ! 823: uint32_t i; ! 824: ! 825: if (firstport + portcount > NB_PORTS) { ! 826: qerror_report(QERR_INVALID_PARAMETER_VALUE, "firstport", ! 827: "firstport on masterbus"); ! 828: error_printf_unless_qmp( ! 829: "firstport value of %u makes companion take ports %u - %u, which " ! 830: "is outside of the valid range of 0 - %u\n", firstport, firstport, ! 831: firstport + portcount - 1, NB_PORTS - 1); ! 832: return -1; ! 833: } ! 834: ! 835: for (i = 0; i < portcount; i++) { ! 836: if (s->companion_ports[firstport + i]) { ! 837: qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus", ! 838: "an USB masterbus"); ! 839: error_printf_unless_qmp( ! 840: "port %u on masterbus %s already has a companion assigned\n", ! 841: firstport + i, bus->qbus.name); ! 842: return -1; ! 843: } ! 844: } ! 845: ! 846: for (i = 0; i < portcount; i++) { ! 847: s->companion_ports[firstport + i] = ports[i]; ! 848: s->ports[firstport + i].speedmask |= ! 849: USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL; ! 850: /* Ensure devs attached before the initial reset go to the companion */ ! 851: s->portsc[firstport + i] = PORTSC_POWNER; ! 852: } ! 853: ! 854: s->companion_count++; ! 855: s->mmio[0x05] = (s->companion_count << 4) | portcount; ! 856: ! 857: return 0; ! 858: } ! 859: ! 860: static USBDevice *ehci_find_device(EHCIState *ehci, uint8_t addr) ! 861: { ! 862: USBDevice *dev; ! 863: USBPort *port; ! 864: int i; ! 865: ! 866: for (i = 0; i < NB_PORTS; i++) { ! 867: port = &ehci->ports[i]; ! 868: if (!(ehci->portsc[i] & PORTSC_PED)) { ! 869: DPRINTF("Port %d not enabled\n", i); ! 870: continue; ! 871: } ! 872: dev = usb_find_device(port, addr); ! 873: if (dev != NULL) { ! 874: return dev; ! 875: } ! 876: } ! 877: return NULL; ! 878: } ! 879: ! 880: /* 4.1 host controller initialization */ ! 881: static void ehci_reset(void *opaque) ! 882: { ! 883: EHCIState *s = opaque; ! 884: int i; ! 885: USBDevice *devs[NB_PORTS]; ! 886: ! 887: trace_usb_ehci_reset(); ! 888: ! 889: /* ! 890: * Do the detach before touching portsc, so that it correctly gets send to ! 891: * us or to our companion based on PORTSC_POWNER before the reset. ! 892: */ ! 893: for(i = 0; i < NB_PORTS; i++) { ! 894: devs[i] = s->ports[i].dev; ! 895: if (devs[i] && devs[i]->attached) { ! 896: usb_detach(&s->ports[i]); ! 897: } ! 898: } ! 899: ! 900: memset(&s->mmio[OPREGBASE], 0x00, MMIO_SIZE - OPREGBASE); ! 901: ! 902: s->usbcmd = NB_MAXINTRATE << USBCMD_ITC_SH; ! 903: s->usbsts = USBSTS_HALT; ! 904: ! 905: s->astate = EST_INACTIVE; ! 906: s->pstate = EST_INACTIVE; ! 907: s->attach_poll_counter = 0; ! 908: ! 909: for(i = 0; i < NB_PORTS; i++) { ! 910: if (s->companion_ports[i]) { ! 911: s->portsc[i] = PORTSC_POWNER | PORTSC_PPOWER; ! 912: } else { ! 913: s->portsc[i] = PORTSC_PPOWER; ! 914: } ! 915: if (devs[i] && devs[i]->attached) { ! 916: usb_attach(&s->ports[i]); ! 917: usb_device_reset(devs[i]); ! 918: } ! 919: } ! 920: ehci_queues_rip_all(s, 0); ! 921: ehci_queues_rip_all(s, 1); ! 922: qemu_del_timer(s->frame_timer); ! 923: } ! 924: ! 925: static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr) ! 926: { ! 927: EHCIState *s = ptr; ! 928: uint32_t val; ! 929: ! 930: val = s->mmio[addr]; ! 931: ! 932: return val; ! 933: } ! 934: ! 935: static uint32_t ehci_mem_readw(void *ptr, target_phys_addr_t addr) ! 936: { ! 937: EHCIState *s = ptr; ! 938: uint32_t val; ! 939: ! 940: val = s->mmio[addr] | (s->mmio[addr+1] << 8); ! 941: ! 942: return val; ! 943: } ! 944: ! 945: static uint32_t ehci_mem_readl(void *ptr, target_phys_addr_t addr) ! 946: { ! 947: EHCIState *s = ptr; ! 948: uint32_t val; ! 949: ! 950: val = s->mmio[addr] | (s->mmio[addr+1] << 8) | ! 951: (s->mmio[addr+2] << 16) | (s->mmio[addr+3] << 24); ! 952: ! 953: trace_usb_ehci_mmio_readl(addr, addr2str(addr), val); ! 954: return val; ! 955: } ! 956: ! 957: static void ehci_mem_writeb(void *ptr, target_phys_addr_t addr, uint32_t val) ! 958: { ! 959: fprintf(stderr, "EHCI doesn't handle byte writes to MMIO\n"); ! 960: exit(1); ! 961: } ! 962: ! 963: static void ehci_mem_writew(void *ptr, target_phys_addr_t addr, uint32_t val) ! 964: { ! 965: fprintf(stderr, "EHCI doesn't handle 16-bit writes to MMIO\n"); ! 966: exit(1); ! 967: } ! 968: ! 969: static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner) ! 970: { ! 971: USBDevice *dev = s->ports[port].dev; ! 972: uint32_t *portsc = &s->portsc[port]; ! 973: uint32_t orig; ! 974: ! 975: if (s->companion_ports[port] == NULL) ! 976: return; ! 977: ! 978: owner = owner & PORTSC_POWNER; ! 979: orig = *portsc & PORTSC_POWNER; ! 980: ! 981: if (!(owner ^ orig)) { ! 982: return; ! 983: } ! 984: ! 985: if (dev && dev->attached) { ! 986: usb_detach(&s->ports[port]); ! 987: } ! 988: ! 989: *portsc &= ~PORTSC_POWNER; ! 990: *portsc |= owner; ! 991: ! 992: if (dev && dev->attached) { ! 993: usb_attach(&s->ports[port]); ! 994: } ! 995: } ! 996: ! 997: static void handle_port_status_write(EHCIState *s, int port, uint32_t val) ! 998: { ! 999: uint32_t *portsc = &s->portsc[port]; ! 1000: USBDevice *dev = s->ports[port].dev; ! 1001: ! 1002: /* Clear rwc bits */ ! 1003: *portsc &= ~(val & PORTSC_RWC_MASK); ! 1004: /* The guest may clear, but not set the PED bit */ ! 1005: *portsc &= val | ~PORTSC_PED; ! 1006: /* POWNER is masked out by RO_MASK as it is RO when we've no companion */ ! 1007: handle_port_owner_write(s, port, val); ! 1008: /* And finally apply RO_MASK */ ! 1009: val &= PORTSC_RO_MASK; ! 1010: ! 1011: if ((val & PORTSC_PRESET) && !(*portsc & PORTSC_PRESET)) { ! 1012: trace_usb_ehci_port_reset(port, 1); ! 1013: } ! 1014: ! 1015: if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) { ! 1016: trace_usb_ehci_port_reset(port, 0); ! 1017: if (dev && dev->attached) { ! 1018: usb_port_reset(&s->ports[port]); ! 1019: *portsc &= ~PORTSC_CSC; ! 1020: } ! 1021: ! 1022: /* ! 1023: * Table 2.16 Set the enable bit(and enable bit change) to indicate ! 1024: * to SW that this port has a high speed device attached ! 1025: */ ! 1026: if (dev && dev->attached && (dev->speedmask & USB_SPEED_MASK_HIGH)) { ! 1027: val |= PORTSC_PED; ! 1028: } ! 1029: } ! 1030: ! 1031: *portsc &= ~PORTSC_RO_MASK; ! 1032: *portsc |= val; ! 1033: } ! 1034: ! 1035: static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) ! 1036: { ! 1037: EHCIState *s = ptr; ! 1038: uint32_t *mmio = (uint32_t *)(&s->mmio[addr]); ! 1039: uint32_t old = *mmio; ! 1040: int i; ! 1041: ! 1042: trace_usb_ehci_mmio_writel(addr, addr2str(addr), val); ! 1043: ! 1044: /* Only aligned reads are allowed on OHCI */ ! 1045: if (addr & 3) { ! 1046: fprintf(stderr, "usb-ehci: Mis-aligned write to addr 0x" ! 1047: TARGET_FMT_plx "\n", addr); ! 1048: return; ! 1049: } ! 1050: ! 1051: if (addr >= PORTSC && addr < PORTSC + 4 * NB_PORTS) { ! 1052: handle_port_status_write(s, (addr-PORTSC)/4, val); ! 1053: trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old); ! 1054: return; ! 1055: } ! 1056: ! 1057: if (addr < OPREGBASE) { ! 1058: fprintf(stderr, "usb-ehci: write attempt to read-only register" ! 1059: TARGET_FMT_plx "\n", addr); ! 1060: return; ! 1061: } ! 1062: ! 1063: ! 1064: /* Do any register specific pre-write processing here. */ ! 1065: switch(addr) { ! 1066: case USBCMD: ! 1067: if ((val & USBCMD_RUNSTOP) && !(s->usbcmd & USBCMD_RUNSTOP)) { ! 1068: qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock)); ! 1069: SET_LAST_RUN_CLOCK(s); ! 1070: ehci_clear_usbsts(s, USBSTS_HALT); ! 1071: } ! 1072: ! 1073: if (!(val & USBCMD_RUNSTOP) && (s->usbcmd & USBCMD_RUNSTOP)) { ! 1074: qemu_del_timer(s->frame_timer); ! 1075: ehci_queues_rip_all(s, 0); ! 1076: ehci_queues_rip_all(s, 1); ! 1077: ehci_set_usbsts(s, USBSTS_HALT); ! 1078: } ! 1079: ! 1080: if (val & USBCMD_HCRESET) { ! 1081: ehci_reset(s); ! 1082: val = s->usbcmd; ! 1083: } ! 1084: ! 1085: /* not supporting dynamic frame list size at the moment */ ! 1086: if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) { ! 1087: fprintf(stderr, "attempt to set frame list size -- value %d\n", ! 1088: val & USBCMD_FLS); ! 1089: val &= ~USBCMD_FLS; ! 1090: } ! 1091: break; ! 1092: ! 1093: case USBSTS: ! 1094: val &= USBSTS_RO_MASK; // bits 6 through 31 are RO ! 1095: ehci_clear_usbsts(s, val); // bits 0 through 5 are R/WC ! 1096: val = s->usbsts; ! 1097: ehci_set_interrupt(s, 0); ! 1098: break; ! 1099: ! 1100: case USBINTR: ! 1101: val &= USBINTR_MASK; ! 1102: break; ! 1103: ! 1104: case FRINDEX: ! 1105: val &= 0x00003ff8; /* frindex is 14bits and always a multiple of 8 */ ! 1106: break; ! 1107: ! 1108: case CONFIGFLAG: ! 1109: val &= 0x1; ! 1110: if (val) { ! 1111: for(i = 0; i < NB_PORTS; i++) ! 1112: handle_port_owner_write(s, i, 0); ! 1113: } ! 1114: break; ! 1115: ! 1116: case PERIODICLISTBASE: ! 1117: if ((s->usbcmd & USBCMD_PSE) && (s->usbcmd & USBCMD_RUNSTOP)) { ! 1118: fprintf(stderr, ! 1119: "ehci: PERIODIC list base register set while periodic schedule\n" ! 1120: " is enabled and HC is enabled\n"); ! 1121: } ! 1122: break; ! 1123: ! 1124: case ASYNCLISTADDR: ! 1125: if ((s->usbcmd & USBCMD_ASE) && (s->usbcmd & USBCMD_RUNSTOP)) { ! 1126: fprintf(stderr, ! 1127: "ehci: ASYNC list address register set while async schedule\n" ! 1128: " is enabled and HC is enabled\n"); ! 1129: } ! 1130: break; ! 1131: } ! 1132: ! 1133: *mmio = val; ! 1134: trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old); ! 1135: } ! 1136: ! 1137: ! 1138: // TODO : Put in common header file, duplication from usb-ohci.c ! 1139: ! 1140: /* Get an array of dwords from main memory */ ! 1141: static inline int get_dwords(EHCIState *ehci, uint32_t addr, ! 1142: uint32_t *buf, int num) ! 1143: { ! 1144: int i; ! 1145: ! 1146: for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { ! 1147: pci_dma_read(&ehci->dev, addr, buf, sizeof(*buf)); ! 1148: *buf = le32_to_cpu(*buf); ! 1149: } ! 1150: ! 1151: return 1; ! 1152: } ! 1153: ! 1154: /* Put an array of dwords in to main memory */ ! 1155: static inline int put_dwords(EHCIState *ehci, uint32_t addr, ! 1156: uint32_t *buf, int num) ! 1157: { ! 1158: int i; ! 1159: ! 1160: for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { ! 1161: uint32_t tmp = cpu_to_le32(*buf); ! 1162: pci_dma_write(&ehci->dev, addr, &tmp, sizeof(tmp)); ! 1163: } ! 1164: ! 1165: return 1; ! 1166: } ! 1167: ! 1168: // 4.10.2 ! 1169: ! 1170: static int ehci_qh_do_overlay(EHCIQueue *q) ! 1171: { ! 1172: int i; ! 1173: int dtoggle; ! 1174: int ping; ! 1175: int eps; ! 1176: int reload; ! 1177: ! 1178: // remember values in fields to preserve in qh after overlay ! 1179: ! 1180: dtoggle = q->qh.token & QTD_TOKEN_DTOGGLE; ! 1181: ping = q->qh.token & QTD_TOKEN_PING; ! 1182: ! 1183: q->qh.current_qtd = q->qtdaddr; ! 1184: q->qh.next_qtd = q->qtd.next; ! 1185: q->qh.altnext_qtd = q->qtd.altnext; ! 1186: q->qh.token = q->qtd.token; ! 1187: ! 1188: ! 1189: eps = get_field(q->qh.epchar, QH_EPCHAR_EPS); ! 1190: if (eps == EHCI_QH_EPS_HIGH) { ! 1191: q->qh.token &= ~QTD_TOKEN_PING; ! 1192: q->qh.token |= ping; ! 1193: } ! 1194: ! 1195: reload = get_field(q->qh.epchar, QH_EPCHAR_RL); ! 1196: set_field(&q->qh.altnext_qtd, reload, QH_ALTNEXT_NAKCNT); ! 1197: ! 1198: for (i = 0; i < 5; i++) { ! 1199: q->qh.bufptr[i] = q->qtd.bufptr[i]; ! 1200: } ! 1201: ! 1202: if (!(q->qh.epchar & QH_EPCHAR_DTC)) { ! 1203: // preserve QH DT bit ! 1204: q->qh.token &= ~QTD_TOKEN_DTOGGLE; ! 1205: q->qh.token |= dtoggle; ! 1206: } ! 1207: ! 1208: q->qh.bufptr[1] &= ~BUFPTR_CPROGMASK_MASK; ! 1209: q->qh.bufptr[2] &= ~BUFPTR_FRAMETAG_MASK; ! 1210: ! 1211: put_dwords(q->ehci, NLPTR_GET(q->qhaddr), (uint32_t *) &q->qh, ! 1212: sizeof(EHCIqh) >> 2); ! 1213: ! 1214: return 0; ! 1215: } ! 1216: ! 1217: static int ehci_init_transfer(EHCIQueue *q) ! 1218: { ! 1219: uint32_t cpage, offset, bytes, plen; ! 1220: dma_addr_t page; ! 1221: ! 1222: cpage = get_field(q->qh.token, QTD_TOKEN_CPAGE); ! 1223: bytes = get_field(q->qh.token, QTD_TOKEN_TBYTES); ! 1224: offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK; ! 1225: pci_dma_sglist_init(&q->sgl, &q->ehci->dev, 5); ! 1226: ! 1227: while (bytes > 0) { ! 1228: if (cpage > 4) { ! 1229: fprintf(stderr, "cpage out of range (%d)\n", cpage); ! 1230: return USB_RET_PROCERR; ! 1231: } ! 1232: ! 1233: page = q->qh.bufptr[cpage] & QTD_BUFPTR_MASK; ! 1234: page += offset; ! 1235: plen = bytes; ! 1236: if (plen > 4096 - offset) { ! 1237: plen = 4096 - offset; ! 1238: offset = 0; ! 1239: cpage++; ! 1240: } ! 1241: ! 1242: qemu_sglist_add(&q->sgl, page, plen); ! 1243: bytes -= plen; ! 1244: } ! 1245: return 0; ! 1246: } ! 1247: ! 1248: static void ehci_finish_transfer(EHCIQueue *q, int status) ! 1249: { ! 1250: uint32_t cpage, offset; ! 1251: ! 1252: qemu_sglist_destroy(&q->sgl); ! 1253: ! 1254: if (status > 0) { ! 1255: /* update cpage & offset */ ! 1256: cpage = get_field(q->qh.token, QTD_TOKEN_CPAGE); ! 1257: offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK; ! 1258: ! 1259: offset += status; ! 1260: cpage += offset >> QTD_BUFPTR_SH; ! 1261: offset &= ~QTD_BUFPTR_MASK; ! 1262: ! 1263: set_field(&q->qh.token, cpage, QTD_TOKEN_CPAGE); ! 1264: q->qh.bufptr[0] &= QTD_BUFPTR_MASK; ! 1265: q->qh.bufptr[0] |= offset; ! 1266: } ! 1267: } ! 1268: ! 1269: static void ehci_async_complete_packet(USBPort *port, USBPacket *packet) ! 1270: { ! 1271: EHCIQueue *q; ! 1272: EHCIState *s = port->opaque; ! 1273: uint32_t portsc = s->portsc[port->index]; ! 1274: ! 1275: if (portsc & PORTSC_POWNER) { ! 1276: USBPort *companion = s->companion_ports[port->index]; ! 1277: companion->ops->complete(companion, packet); ! 1278: return; ! 1279: } ! 1280: ! 1281: q = container_of(packet, EHCIQueue, packet); ! 1282: trace_usb_ehci_queue_action(q, "wakeup"); ! 1283: assert(q->async == EHCI_ASYNC_INFLIGHT); ! 1284: q->async = EHCI_ASYNC_FINISHED; ! 1285: q->usb_status = packet->result; ! 1286: } ! 1287: ! 1288: static void ehci_execute_complete(EHCIQueue *q) ! 1289: { ! 1290: assert(q->async != EHCI_ASYNC_INFLIGHT); ! 1291: q->async = EHCI_ASYNC_NONE; ! 1292: ! 1293: DPRINTF("execute_complete: qhaddr 0x%x, next %x, qtdaddr 0x%x, status %d\n", ! 1294: q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status); ! 1295: ! 1296: if (q->usb_status < 0) { ! 1297: switch(q->usb_status) { ! 1298: case USB_RET_IOERROR: ! 1299: case USB_RET_NODEV: ! 1300: q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR); ! 1301: set_field(&q->qh.token, 0, QTD_TOKEN_CERR); ! 1302: ehci_record_interrupt(q->ehci, USBSTS_ERRINT); ! 1303: break; ! 1304: case USB_RET_STALL: ! 1305: q->qh.token |= QTD_TOKEN_HALT; ! 1306: ehci_record_interrupt(q->ehci, USBSTS_ERRINT); ! 1307: break; ! 1308: case USB_RET_NAK: ! 1309: set_field(&q->qh.altnext_qtd, 0, QH_ALTNEXT_NAKCNT); ! 1310: return; /* We're not done yet with this transaction */ ! 1311: case USB_RET_BABBLE: ! 1312: q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE); ! 1313: ehci_record_interrupt(q->ehci, USBSTS_ERRINT); ! 1314: break; ! 1315: default: ! 1316: /* should not be triggerable */ ! 1317: fprintf(stderr, "USB invalid response %d to handle\n", q->usb_status); ! 1318: assert(0); ! 1319: break; ! 1320: } ! 1321: } else if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) { ! 1322: q->usb_status = USB_RET_BABBLE; ! 1323: q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE); ! 1324: ehci_record_interrupt(q->ehci, USBSTS_ERRINT); ! 1325: } else { ! 1326: // TODO check 4.12 for splits ! 1327: ! 1328: if (q->tbytes && q->pid == USB_TOKEN_IN) { ! 1329: q->tbytes -= q->usb_status; ! 1330: } else { ! 1331: q->tbytes = 0; ! 1332: } ! 1333: ! 1334: DPRINTF("updating tbytes to %d\n", q->tbytes); ! 1335: set_field(&q->qh.token, q->tbytes, QTD_TOKEN_TBYTES); ! 1336: } ! 1337: ehci_finish_transfer(q, q->usb_status); ! 1338: usb_packet_unmap(&q->packet); ! 1339: ! 1340: q->qh.token ^= QTD_TOKEN_DTOGGLE; ! 1341: q->qh.token &= ~QTD_TOKEN_ACTIVE; ! 1342: ! 1343: if (q->qh.token & QTD_TOKEN_IOC) { ! 1344: ehci_record_interrupt(q->ehci, USBSTS_INT); ! 1345: } ! 1346: } ! 1347: ! 1348: // 4.10.3 ! 1349: ! 1350: static int ehci_execute(EHCIQueue *q) ! 1351: { ! 1352: USBDevice *dev; ! 1353: USBEndpoint *ep; ! 1354: int ret; ! 1355: int endp; ! 1356: int devadr; ! 1357: ! 1358: if ( !(q->qh.token & QTD_TOKEN_ACTIVE)) { ! 1359: fprintf(stderr, "Attempting to execute inactive QH\n"); ! 1360: return USB_RET_PROCERR; ! 1361: } ! 1362: ! 1363: q->tbytes = (q->qh.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH; ! 1364: if (q->tbytes > BUFF_SIZE) { ! 1365: fprintf(stderr, "Request for more bytes than allowed\n"); ! 1366: return USB_RET_PROCERR; ! 1367: } ! 1368: ! 1369: q->pid = (q->qh.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH; ! 1370: switch(q->pid) { ! 1371: case 0: q->pid = USB_TOKEN_OUT; break; ! 1372: case 1: q->pid = USB_TOKEN_IN; break; ! 1373: case 2: q->pid = USB_TOKEN_SETUP; break; ! 1374: default: fprintf(stderr, "bad token\n"); break; ! 1375: } ! 1376: ! 1377: if (ehci_init_transfer(q) != 0) { ! 1378: return USB_RET_PROCERR; ! 1379: } ! 1380: ! 1381: endp = get_field(q->qh.epchar, QH_EPCHAR_EP); ! 1382: devadr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR); ! 1383: ! 1384: /* TODO: associating device with ehci port */ ! 1385: dev = ehci_find_device(q->ehci, devadr); ! 1386: ep = usb_ep_get(dev, q->pid, endp); ! 1387: ! 1388: usb_packet_setup(&q->packet, q->pid, ep); ! 1389: usb_packet_map(&q->packet, &q->sgl); ! 1390: ! 1391: ret = usb_handle_packet(dev, &q->packet); ! 1392: DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd " ! 1393: "(total %d) endp %x ret %d\n", ! 1394: q->qhaddr, q->qh.next, q->qtdaddr, q->pid, ! 1395: q->packet.iov.size, q->tbytes, endp, ret); ! 1396: ! 1397: if (ret > BUFF_SIZE) { ! 1398: fprintf(stderr, "ret from usb_handle_packet > BUFF_SIZE\n"); ! 1399: return USB_RET_PROCERR; ! 1400: } ! 1401: ! 1402: return ret; ! 1403: } ! 1404: ! 1405: /* 4.7.2 ! 1406: */ ! 1407: ! 1408: static int ehci_process_itd(EHCIState *ehci, ! 1409: EHCIitd *itd) ! 1410: { ! 1411: USBDevice *dev; ! 1412: USBEndpoint *ep; ! 1413: int ret; ! 1414: uint32_t i, len, pid, dir, devaddr, endp; ! 1415: uint32_t pg, off, ptr1, ptr2, max, mult; ! 1416: ! 1417: dir =(itd->bufptr[1] & ITD_BUFPTR_DIRECTION); ! 1418: devaddr = get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR); ! 1419: endp = get_field(itd->bufptr[0], ITD_BUFPTR_EP); ! 1420: max = get_field(itd->bufptr[1], ITD_BUFPTR_MAXPKT); ! 1421: mult = get_field(itd->bufptr[2], ITD_BUFPTR_MULT); ! 1422: ! 1423: for(i = 0; i < 8; i++) { ! 1424: if (itd->transact[i] & ITD_XACT_ACTIVE) { ! 1425: pg = get_field(itd->transact[i], ITD_XACT_PGSEL); ! 1426: off = itd->transact[i] & ITD_XACT_OFFSET_MASK; ! 1427: ptr1 = (itd->bufptr[pg] & ITD_BUFPTR_MASK); ! 1428: ptr2 = (itd->bufptr[pg+1] & ITD_BUFPTR_MASK); ! 1429: len = get_field(itd->transact[i], ITD_XACT_LENGTH); ! 1430: ! 1431: if (len > max * mult) { ! 1432: len = max * mult; ! 1433: } ! 1434: ! 1435: if (len > BUFF_SIZE) { ! 1436: return USB_RET_PROCERR; ! 1437: } ! 1438: ! 1439: pci_dma_sglist_init(&ehci->isgl, &ehci->dev, 2); ! 1440: if (off + len > 4096) { ! 1441: /* transfer crosses page border */ ! 1442: uint32_t len2 = off + len - 4096; ! 1443: uint32_t len1 = len - len2; ! 1444: qemu_sglist_add(&ehci->isgl, ptr1 + off, len1); ! 1445: qemu_sglist_add(&ehci->isgl, ptr2, len2); ! 1446: } else { ! 1447: qemu_sglist_add(&ehci->isgl, ptr1 + off, len); ! 1448: } ! 1449: ! 1450: pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT; ! 1451: ! 1452: dev = ehci_find_device(ehci, devaddr); ! 1453: ep = usb_ep_get(dev, pid, endp); ! 1454: if (ep->type == USB_ENDPOINT_XFER_ISOC) { ! 1455: usb_packet_setup(&ehci->ipacket, pid, ep); ! 1456: usb_packet_map(&ehci->ipacket, &ehci->isgl); ! 1457: ret = usb_handle_packet(dev, &ehci->ipacket); ! 1458: assert(ret != USB_RET_ASYNC); ! 1459: usb_packet_unmap(&ehci->ipacket); ! 1460: } else { ! 1461: DPRINTF("ISOCH: attempt to addess non-iso endpoint\n"); ! 1462: ret = USB_RET_NAK; ! 1463: } ! 1464: qemu_sglist_destroy(&ehci->isgl); ! 1465: ! 1466: if (ret < 0) { ! 1467: switch (ret) { ! 1468: default: ! 1469: fprintf(stderr, "Unexpected iso usb result: %d\n", ret); ! 1470: /* Fall through */ ! 1471: case USB_RET_IOERROR: ! 1472: case USB_RET_NODEV: ! 1473: /* 3.3.2: XACTERR is only allowed on IN transactions */ ! 1474: if (dir) { ! 1475: itd->transact[i] |= ITD_XACT_XACTERR; ! 1476: ehci_record_interrupt(ehci, USBSTS_ERRINT); ! 1477: } ! 1478: break; ! 1479: case USB_RET_BABBLE: ! 1480: itd->transact[i] |= ITD_XACT_BABBLE; ! 1481: ehci_record_interrupt(ehci, USBSTS_ERRINT); ! 1482: break; ! 1483: case USB_RET_NAK: ! 1484: /* no data for us, so do a zero-length transfer */ ! 1485: ret = 0; ! 1486: break; ! 1487: } ! 1488: } ! 1489: if (ret >= 0) { ! 1490: if (!dir) { ! 1491: /* OUT */ ! 1492: set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH); ! 1493: } else { ! 1494: /* IN */ ! 1495: set_field(&itd->transact[i], ret, ITD_XACT_LENGTH); ! 1496: } ! 1497: } ! 1498: if (itd->transact[i] & ITD_XACT_IOC) { ! 1499: ehci_record_interrupt(ehci, USBSTS_INT); ! 1500: } ! 1501: itd->transact[i] &= ~ITD_XACT_ACTIVE; ! 1502: } ! 1503: } ! 1504: return 0; ! 1505: } ! 1506: ! 1507: /* This state is the entry point for asynchronous schedule ! 1508: * processing. Entry here consitutes a EHCI start event state (4.8.5) ! 1509: */ ! 1510: static int ehci_state_waitlisthead(EHCIState *ehci, int async) ! 1511: { ! 1512: EHCIqh qh; ! 1513: int i = 0; ! 1514: int again = 0; ! 1515: uint32_t entry = ehci->asynclistaddr; ! 1516: ! 1517: /* set reclamation flag at start event (4.8.6) */ ! 1518: if (async) { ! 1519: ehci_set_usbsts(ehci, USBSTS_REC); ! 1520: } ! 1521: ! 1522: ehci_queues_rip_unused(ehci, async, 0); ! 1523: ! 1524: /* Find the head of the list (4.9.1.1) */ ! 1525: for(i = 0; i < MAX_QH; i++) { ! 1526: get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &qh, ! 1527: sizeof(EHCIqh) >> 2); ! 1528: ehci_trace_qh(NULL, NLPTR_GET(entry), &qh); ! 1529: ! 1530: if (qh.epchar & QH_EPCHAR_H) { ! 1531: if (async) { ! 1532: entry |= (NLPTR_TYPE_QH << 1); ! 1533: } ! 1534: ! 1535: ehci_set_fetch_addr(ehci, async, entry); ! 1536: ehci_set_state(ehci, async, EST_FETCHENTRY); ! 1537: again = 1; ! 1538: goto out; ! 1539: } ! 1540: ! 1541: entry = qh.next; ! 1542: if (entry == ehci->asynclistaddr) { ! 1543: break; ! 1544: } ! 1545: } ! 1546: ! 1547: /* no head found for list. */ ! 1548: ! 1549: ehci_set_state(ehci, async, EST_ACTIVE); ! 1550: ! 1551: out: ! 1552: return again; ! 1553: } ! 1554: ! 1555: ! 1556: /* This state is the entry point for periodic schedule processing as ! 1557: * well as being a continuation state for async processing. ! 1558: */ ! 1559: static int ehci_state_fetchentry(EHCIState *ehci, int async) ! 1560: { ! 1561: int again = 0; ! 1562: uint32_t entry = ehci_get_fetch_addr(ehci, async); ! 1563: ! 1564: if (NLPTR_TBIT(entry)) { ! 1565: ehci_set_state(ehci, async, EST_ACTIVE); ! 1566: goto out; ! 1567: } ! 1568: ! 1569: /* section 4.8, only QH in async schedule */ ! 1570: if (async && (NLPTR_TYPE_GET(entry) != NLPTR_TYPE_QH)) { ! 1571: fprintf(stderr, "non queue head request in async schedule\n"); ! 1572: return -1; ! 1573: } ! 1574: ! 1575: switch (NLPTR_TYPE_GET(entry)) { ! 1576: case NLPTR_TYPE_QH: ! 1577: ehci_set_state(ehci, async, EST_FETCHQH); ! 1578: again = 1; ! 1579: break; ! 1580: ! 1581: case NLPTR_TYPE_ITD: ! 1582: ehci_set_state(ehci, async, EST_FETCHITD); ! 1583: again = 1; ! 1584: break; ! 1585: ! 1586: case NLPTR_TYPE_STITD: ! 1587: ehci_set_state(ehci, async, EST_FETCHSITD); ! 1588: again = 1; ! 1589: break; ! 1590: ! 1591: default: ! 1592: /* TODO: handle FSTN type */ ! 1593: fprintf(stderr, "FETCHENTRY: entry at %X is of type %d " ! 1594: "which is not supported yet\n", entry, NLPTR_TYPE_GET(entry)); ! 1595: return -1; ! 1596: } ! 1597: ! 1598: out: ! 1599: return again; ! 1600: } ! 1601: ! 1602: static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) ! 1603: { ! 1604: uint32_t entry; ! 1605: EHCIQueue *q; ! 1606: ! 1607: entry = ehci_get_fetch_addr(ehci, async); ! 1608: q = ehci_find_queue_by_qh(ehci, entry, async); ! 1609: if (NULL == q) { ! 1610: q = ehci_alloc_queue(ehci, async); ! 1611: } ! 1612: q->qhaddr = entry; ! 1613: q->seen++; ! 1614: ! 1615: if (q->seen > 1) { ! 1616: /* we are going in circles -- stop processing */ ! 1617: ehci_set_state(ehci, async, EST_ACTIVE); ! 1618: q = NULL; ! 1619: goto out; ! 1620: } ! 1621: ! 1622: get_dwords(ehci, NLPTR_GET(q->qhaddr), ! 1623: (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2); ! 1624: ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh); ! 1625: ! 1626: if (q->async == EHCI_ASYNC_INFLIGHT) { ! 1627: /* I/O still in progress -- skip queue */ ! 1628: ehci_set_state(ehci, async, EST_HORIZONTALQH); ! 1629: goto out; ! 1630: } ! 1631: if (q->async == EHCI_ASYNC_FINISHED) { ! 1632: /* I/O finished -- continue processing queue */ ! 1633: trace_usb_ehci_queue_action(q, "resume"); ! 1634: ehci_set_state(ehci, async, EST_EXECUTING); ! 1635: goto out; ! 1636: } ! 1637: ! 1638: if (async && (q->qh.epchar & QH_EPCHAR_H)) { ! 1639: ! 1640: /* EHCI spec version 1.0 Section 4.8.3 & 4.10.1 */ ! 1641: if (ehci->usbsts & USBSTS_REC) { ! 1642: ehci_clear_usbsts(ehci, USBSTS_REC); ! 1643: } else { ! 1644: DPRINTF("FETCHQH: QH 0x%08x. H-bit set, reclamation status reset" ! 1645: " - done processing\n", q->qhaddr); ! 1646: ehci_set_state(ehci, async, EST_ACTIVE); ! 1647: q = NULL; ! 1648: goto out; ! 1649: } ! 1650: } ! 1651: ! 1652: #if EHCI_DEBUG ! 1653: if (q->qhaddr != q->qh.next) { ! 1654: DPRINTF("FETCHQH: QH 0x%08x (h %x halt %x active %x) next 0x%08x\n", ! 1655: q->qhaddr, ! 1656: q->qh.epchar & QH_EPCHAR_H, ! 1657: q->qh.token & QTD_TOKEN_HALT, ! 1658: q->qh.token & QTD_TOKEN_ACTIVE, ! 1659: q->qh.next); ! 1660: } ! 1661: #endif ! 1662: ! 1663: if (q->qh.token & QTD_TOKEN_HALT) { ! 1664: ehci_set_state(ehci, async, EST_HORIZONTALQH); ! 1665: ! 1666: } else if ((q->qh.token & QTD_TOKEN_ACTIVE) && ! 1667: (NLPTR_TBIT(q->qh.current_qtd) == 0)) { ! 1668: q->qtdaddr = q->qh.current_qtd; ! 1669: ehci_set_state(ehci, async, EST_FETCHQTD); ! 1670: ! 1671: } else { ! 1672: /* EHCI spec version 1.0 Section 4.10.2 */ ! 1673: ehci_set_state(ehci, async, EST_ADVANCEQUEUE); ! 1674: } ! 1675: ! 1676: out: ! 1677: return q; ! 1678: } ! 1679: ! 1680: static int ehci_state_fetchitd(EHCIState *ehci, int async) ! 1681: { ! 1682: uint32_t entry; ! 1683: EHCIitd itd; ! 1684: ! 1685: assert(!async); ! 1686: entry = ehci_get_fetch_addr(ehci, async); ! 1687: ! 1688: get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &itd, ! 1689: sizeof(EHCIitd) >> 2); ! 1690: ehci_trace_itd(ehci, entry, &itd); ! 1691: ! 1692: if (ehci_process_itd(ehci, &itd) != 0) { ! 1693: return -1; ! 1694: } ! 1695: ! 1696: put_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &itd, ! 1697: sizeof(EHCIitd) >> 2); ! 1698: ehci_set_fetch_addr(ehci, async, itd.next); ! 1699: ehci_set_state(ehci, async, EST_FETCHENTRY); ! 1700: ! 1701: return 1; ! 1702: } ! 1703: ! 1704: static int ehci_state_fetchsitd(EHCIState *ehci, int async) ! 1705: { ! 1706: uint32_t entry; ! 1707: EHCIsitd sitd; ! 1708: ! 1709: assert(!async); ! 1710: entry = ehci_get_fetch_addr(ehci, async); ! 1711: ! 1712: get_dwords(ehci, NLPTR_GET(entry), (uint32_t *)&sitd, ! 1713: sizeof(EHCIsitd) >> 2); ! 1714: ehci_trace_sitd(ehci, entry, &sitd); ! 1715: ! 1716: if (!(sitd.results & SITD_RESULTS_ACTIVE)) { ! 1717: /* siTD is not active, nothing to do */; ! 1718: } else { ! 1719: /* TODO: split transfers are not implemented */ ! 1720: fprintf(stderr, "WARNING: Skipping active siTD\n"); ! 1721: } ! 1722: ! 1723: ehci_set_fetch_addr(ehci, async, sitd.next); ! 1724: ehci_set_state(ehci, async, EST_FETCHENTRY); ! 1725: return 1; ! 1726: } ! 1727: ! 1728: /* Section 4.10.2 - paragraph 3 */ ! 1729: static int ehci_state_advqueue(EHCIQueue *q, int async) ! 1730: { ! 1731: #if 0 ! 1732: /* TO-DO: 4.10.2 - paragraph 2 ! 1733: * if I-bit is set to 1 and QH is not active ! 1734: * go to horizontal QH ! 1735: */ ! 1736: if (I-bit set) { ! 1737: ehci_set_state(ehci, async, EST_HORIZONTALQH); ! 1738: goto out; ! 1739: } ! 1740: #endif ! 1741: ! 1742: /* ! 1743: * want data and alt-next qTD is valid ! 1744: */ ! 1745: if (((q->qh.token & QTD_TOKEN_TBYTES_MASK) != 0) && ! 1746: (NLPTR_TBIT(q->qh.altnext_qtd) == 0)) { ! 1747: q->qtdaddr = q->qh.altnext_qtd; ! 1748: ehci_set_state(q->ehci, async, EST_FETCHQTD); ! 1749: ! 1750: /* ! 1751: * next qTD is valid ! 1752: */ ! 1753: } else if (NLPTR_TBIT(q->qh.next_qtd) == 0) { ! 1754: q->qtdaddr = q->qh.next_qtd; ! 1755: ehci_set_state(q->ehci, async, EST_FETCHQTD); ! 1756: ! 1757: /* ! 1758: * no valid qTD, try next QH ! 1759: */ ! 1760: } else { ! 1761: ehci_set_state(q->ehci, async, EST_HORIZONTALQH); ! 1762: } ! 1763: ! 1764: return 1; ! 1765: } ! 1766: ! 1767: /* Section 4.10.2 - paragraph 4 */ ! 1768: static int ehci_state_fetchqtd(EHCIQueue *q, int async) ! 1769: { ! 1770: int again = 0; ! 1771: ! 1772: get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &q->qtd, ! 1773: sizeof(EHCIqtd) >> 2); ! 1774: ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &q->qtd); ! 1775: ! 1776: if (q->qtd.token & QTD_TOKEN_ACTIVE) { ! 1777: ehci_set_state(q->ehci, async, EST_EXECUTE); ! 1778: again = 1; ! 1779: } else { ! 1780: ehci_set_state(q->ehci, async, EST_HORIZONTALQH); ! 1781: again = 1; ! 1782: } ! 1783: ! 1784: return again; ! 1785: } ! 1786: ! 1787: static int ehci_state_horizqh(EHCIQueue *q, int async) ! 1788: { ! 1789: int again = 0; ! 1790: ! 1791: if (ehci_get_fetch_addr(q->ehci, async) != q->qh.next) { ! 1792: ehci_set_fetch_addr(q->ehci, async, q->qh.next); ! 1793: ehci_set_state(q->ehci, async, EST_FETCHENTRY); ! 1794: again = 1; ! 1795: } else { ! 1796: ehci_set_state(q->ehci, async, EST_ACTIVE); ! 1797: } ! 1798: ! 1799: return again; ! 1800: } ! 1801: ! 1802: /* ! 1803: * Write the qh back to guest physical memory. This step isn't ! 1804: * in the EHCI spec but we need to do it since we don't share ! 1805: * physical memory with our guest VM. ! 1806: * ! 1807: * The first three dwords are read-only for the EHCI, so skip them ! 1808: * when writing back the qh. ! 1809: */ ! 1810: static void ehci_flush_qh(EHCIQueue *q) ! 1811: { ! 1812: uint32_t *qh = (uint32_t *) &q->qh; ! 1813: uint32_t dwords = sizeof(EHCIqh) >> 2; ! 1814: uint32_t addr = NLPTR_GET(q->qhaddr); ! 1815: ! 1816: put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3); ! 1817: } ! 1818: ! 1819: static int ehci_state_execute(EHCIQueue *q, int async) ! 1820: { ! 1821: int again = 0; ! 1822: ! 1823: if (ehci_qh_do_overlay(q) != 0) { ! 1824: return -1; ! 1825: } ! 1826: ! 1827: // TODO verify enough time remains in the uframe as in 4.4.1.1 ! 1828: // TODO write back ptr to async list when done or out of time ! 1829: // TODO Windows does not seem to ever set the MULT field ! 1830: ! 1831: if (!async) { ! 1832: int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT); ! 1833: if (!transactCtr) { ! 1834: ehci_set_state(q->ehci, async, EST_HORIZONTALQH); ! 1835: again = 1; ! 1836: goto out; ! 1837: } ! 1838: } ! 1839: ! 1840: if (async) { ! 1841: ehci_set_usbsts(q->ehci, USBSTS_REC); ! 1842: } ! 1843: ! 1844: q->usb_status = ehci_execute(q); ! 1845: if (q->usb_status == USB_RET_PROCERR) { ! 1846: again = -1; ! 1847: goto out; ! 1848: } ! 1849: if (q->usb_status == USB_RET_ASYNC) { ! 1850: ehci_flush_qh(q); ! 1851: trace_usb_ehci_queue_action(q, "suspend"); ! 1852: q->async = EHCI_ASYNC_INFLIGHT; ! 1853: ehci_set_state(q->ehci, async, EST_HORIZONTALQH); ! 1854: again = 1; ! 1855: goto out; ! 1856: } ! 1857: ! 1858: ehci_set_state(q->ehci, async, EST_EXECUTING); ! 1859: again = 1; ! 1860: ! 1861: out: ! 1862: return again; ! 1863: } ! 1864: ! 1865: static int ehci_state_executing(EHCIQueue *q, int async) ! 1866: { ! 1867: int again = 0; ! 1868: ! 1869: ehci_execute_complete(q); ! 1870: if (q->usb_status == USB_RET_ASYNC) { ! 1871: goto out; ! 1872: } ! 1873: if (q->usb_status == USB_RET_PROCERR) { ! 1874: again = -1; ! 1875: goto out; ! 1876: } ! 1877: ! 1878: // 4.10.3 ! 1879: if (!async) { ! 1880: int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT); ! 1881: transactCtr--; ! 1882: set_field(&q->qh.epcap, transactCtr, QH_EPCAP_MULT); ! 1883: // 4.10.3, bottom of page 82, should exit this state when transaction ! 1884: // counter decrements to 0 ! 1885: } ! 1886: ! 1887: /* 4.10.5 */ ! 1888: if (q->usb_status == USB_RET_NAK) { ! 1889: ehci_set_state(q->ehci, async, EST_HORIZONTALQH); ! 1890: } else { ! 1891: ehci_set_state(q->ehci, async, EST_WRITEBACK); ! 1892: } ! 1893: ! 1894: again = 1; ! 1895: ! 1896: out: ! 1897: ehci_flush_qh(q); ! 1898: return again; ! 1899: } ! 1900: ! 1901: ! 1902: static int ehci_state_writeback(EHCIQueue *q, int async) ! 1903: { ! 1904: int again = 0; ! 1905: ! 1906: /* Write back the QTD from the QH area */ ! 1907: ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), (EHCIqtd*) &q->qh.next_qtd); ! 1908: put_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &q->qh.next_qtd, ! 1909: sizeof(EHCIqtd) >> 2); ! 1910: ! 1911: /* ! 1912: * EHCI specs say go horizontal here. ! 1913: * ! 1914: * We can also advance the queue here for performance reasons. We ! 1915: * need to take care to only take that shortcut in case we've ! 1916: * processed the qtd just written back without errors, i.e. halt ! 1917: * bit is clear. ! 1918: */ ! 1919: if (q->qh.token & QTD_TOKEN_HALT) { ! 1920: ehci_set_state(q->ehci, async, EST_HORIZONTALQH); ! 1921: again = 1; ! 1922: } else { ! 1923: ehci_set_state(q->ehci, async, EST_ADVANCEQUEUE); ! 1924: again = 1; ! 1925: } ! 1926: return again; ! 1927: } ! 1928: ! 1929: /* ! 1930: * This is the state machine that is common to both async and periodic ! 1931: */ ! 1932: ! 1933: static void ehci_advance_state(EHCIState *ehci, ! 1934: int async) ! 1935: { ! 1936: EHCIQueue *q = NULL; ! 1937: int again; ! 1938: ! 1939: do { ! 1940: switch(ehci_get_state(ehci, async)) { ! 1941: case EST_WAITLISTHEAD: ! 1942: again = ehci_state_waitlisthead(ehci, async); ! 1943: break; ! 1944: ! 1945: case EST_FETCHENTRY: ! 1946: again = ehci_state_fetchentry(ehci, async); ! 1947: break; ! 1948: ! 1949: case EST_FETCHQH: ! 1950: q = ehci_state_fetchqh(ehci, async); ! 1951: again = q ? 1 : 0; ! 1952: break; ! 1953: ! 1954: case EST_FETCHITD: ! 1955: again = ehci_state_fetchitd(ehci, async); ! 1956: break; ! 1957: ! 1958: case EST_FETCHSITD: ! 1959: again = ehci_state_fetchsitd(ehci, async); ! 1960: break; ! 1961: ! 1962: case EST_ADVANCEQUEUE: ! 1963: again = ehci_state_advqueue(q, async); ! 1964: break; ! 1965: ! 1966: case EST_FETCHQTD: ! 1967: again = ehci_state_fetchqtd(q, async); ! 1968: break; ! 1969: ! 1970: case EST_HORIZONTALQH: ! 1971: again = ehci_state_horizqh(q, async); ! 1972: break; ! 1973: ! 1974: case EST_EXECUTE: ! 1975: again = ehci_state_execute(q, async); ! 1976: break; ! 1977: ! 1978: case EST_EXECUTING: ! 1979: assert(q != NULL); ! 1980: again = ehci_state_executing(q, async); ! 1981: break; ! 1982: ! 1983: case EST_WRITEBACK: ! 1984: assert(q != NULL); ! 1985: again = ehci_state_writeback(q, async); ! 1986: break; ! 1987: ! 1988: default: ! 1989: fprintf(stderr, "Bad state!\n"); ! 1990: again = -1; ! 1991: assert(0); ! 1992: break; ! 1993: } ! 1994: ! 1995: if (again < 0) { ! 1996: fprintf(stderr, "processing error - resetting ehci HC\n"); ! 1997: ehci_reset(ehci); ! 1998: again = 0; ! 1999: } ! 2000: } ! 2001: while (again); ! 2002: ! 2003: ehci_commit_interrupt(ehci); ! 2004: } ! 2005: ! 2006: static void ehci_advance_async_state(EHCIState *ehci) ! 2007: { ! 2008: const int async = 1; ! 2009: ! 2010: switch(ehci_get_state(ehci, async)) { ! 2011: case EST_INACTIVE: ! 2012: if (!(ehci->usbcmd & USBCMD_ASE)) { ! 2013: break; ! 2014: } ! 2015: ehci_set_usbsts(ehci, USBSTS_ASS); ! 2016: ehci_set_state(ehci, async, EST_ACTIVE); ! 2017: // No break, fall through to ACTIVE ! 2018: ! 2019: case EST_ACTIVE: ! 2020: if ( !(ehci->usbcmd & USBCMD_ASE)) { ! 2021: ehci_queues_rip_all(ehci, async); ! 2022: ehci_clear_usbsts(ehci, USBSTS_ASS); ! 2023: ehci_set_state(ehci, async, EST_INACTIVE); ! 2024: break; ! 2025: } ! 2026: ! 2027: /* make sure guest has acknowledged the doorbell interrupt */ ! 2028: /* TO-DO: is this really needed? */ ! 2029: if (ehci->usbsts & USBSTS_IAA) { ! 2030: DPRINTF("IAA status bit still set.\n"); ! 2031: break; ! 2032: } ! 2033: ! 2034: /* check that address register has been set */ ! 2035: if (ehci->asynclistaddr == 0) { ! 2036: break; ! 2037: } ! 2038: ! 2039: ehci_set_state(ehci, async, EST_WAITLISTHEAD); ! 2040: ehci_advance_state(ehci, async); ! 2041: ! 2042: /* If the doorbell is set, the guest wants to make a change to the ! 2043: * schedule. The host controller needs to release cached data. ! 2044: * (section 4.8.2) ! 2045: */ ! 2046: if (ehci->usbcmd & USBCMD_IAAD) { ! 2047: /* Remove all unseen qhs from the async qhs queue */ ! 2048: ehci_queues_rip_unused(ehci, async, 1); ! 2049: DPRINTF("ASYNC: doorbell request acknowledged\n"); ! 2050: ehci->usbcmd &= ~USBCMD_IAAD; ! 2051: ehci_set_interrupt(ehci, USBSTS_IAA); ! 2052: } ! 2053: break; ! 2054: ! 2055: default: ! 2056: /* this should only be due to a developer mistake */ ! 2057: fprintf(stderr, "ehci: Bad asynchronous state %d. " ! 2058: "Resetting to active\n", ehci->astate); ! 2059: assert(0); ! 2060: } ! 2061: } ! 2062: ! 2063: static void ehci_advance_periodic_state(EHCIState *ehci) ! 2064: { ! 2065: uint32_t entry; ! 2066: uint32_t list; ! 2067: const int async = 0; ! 2068: ! 2069: // 4.6 ! 2070: ! 2071: switch(ehci_get_state(ehci, async)) { ! 2072: case EST_INACTIVE: ! 2073: if ( !(ehci->frindex & 7) && (ehci->usbcmd & USBCMD_PSE)) { ! 2074: ehci_set_usbsts(ehci, USBSTS_PSS); ! 2075: ehci_set_state(ehci, async, EST_ACTIVE); ! 2076: // No break, fall through to ACTIVE ! 2077: } else ! 2078: break; ! 2079: ! 2080: case EST_ACTIVE: ! 2081: if ( !(ehci->frindex & 7) && !(ehci->usbcmd & USBCMD_PSE)) { ! 2082: ehci_queues_rip_all(ehci, async); ! 2083: ehci_clear_usbsts(ehci, USBSTS_PSS); ! 2084: ehci_set_state(ehci, async, EST_INACTIVE); ! 2085: break; ! 2086: } ! 2087: ! 2088: list = ehci->periodiclistbase & 0xfffff000; ! 2089: /* check that register has been set */ ! 2090: if (list == 0) { ! 2091: break; ! 2092: } ! 2093: list |= ((ehci->frindex & 0x1ff8) >> 1); ! 2094: ! 2095: pci_dma_read(&ehci->dev, list, &entry, sizeof entry); ! 2096: entry = le32_to_cpu(entry); ! 2097: ! 2098: DPRINTF("PERIODIC state adv fr=%d. [%08X] -> %08X\n", ! 2099: ehci->frindex / 8, list, entry); ! 2100: ehci_set_fetch_addr(ehci, async,entry); ! 2101: ehci_set_state(ehci, async, EST_FETCHENTRY); ! 2102: ehci_advance_state(ehci, async); ! 2103: ehci_queues_rip_unused(ehci, async, 0); ! 2104: break; ! 2105: ! 2106: default: ! 2107: /* this should only be due to a developer mistake */ ! 2108: fprintf(stderr, "ehci: Bad periodic state %d. " ! 2109: "Resetting to active\n", ehci->pstate); ! 2110: assert(0); ! 2111: } ! 2112: } ! 2113: ! 2114: static void ehci_frame_timer(void *opaque) ! 2115: { ! 2116: EHCIState *ehci = opaque; ! 2117: int64_t expire_time, t_now; ! 2118: uint64_t ns_elapsed; ! 2119: int frames; ! 2120: int i; ! 2121: int skipped_frames = 0; ! 2122: ! 2123: t_now = qemu_get_clock_ns(vm_clock); ! 2124: expire_time = t_now + (get_ticks_per_sec() / ehci->freq); ! 2125: ! 2126: ns_elapsed = t_now - ehci->last_run_ns; ! 2127: frames = ns_elapsed / FRAME_TIMER_NS; ! 2128: ! 2129: for (i = 0; i < frames; i++) { ! 2130: if ( !(ehci->usbsts & USBSTS_HALT)) { ! 2131: ehci->frindex += 8; ! 2132: ! 2133: if (ehci->frindex == 0x00002000) { ! 2134: ehci_set_interrupt(ehci, USBSTS_FLR); ! 2135: } ! 2136: ! 2137: if (ehci->frindex == 0x00004000) { ! 2138: ehci_set_interrupt(ehci, USBSTS_FLR); ! 2139: ehci->frindex = 0; ! 2140: } ! 2141: } ! 2142: ! 2143: if (frames - i > ehci->maxframes) { ! 2144: skipped_frames++; ! 2145: } else { ! 2146: ehci_advance_periodic_state(ehci); ! 2147: } ! 2148: ! 2149: ehci->last_run_ns += FRAME_TIMER_NS; ! 2150: } ! 2151: ! 2152: #if 0 ! 2153: if (skipped_frames) { ! 2154: DPRINTF("WARNING - EHCI skipped %d frames\n", skipped_frames); ! 2155: } ! 2156: #endif ! 2157: ! 2158: /* Async is not inside loop since it executes everything it can once ! 2159: * called ! 2160: */ ! 2161: ehci_advance_async_state(ehci); ! 2162: ! 2163: qemu_mod_timer(ehci->frame_timer, expire_time); ! 2164: } ! 2165: ! 2166: ! 2167: static const MemoryRegionOps ehci_mem_ops = { ! 2168: .old_mmio = { ! 2169: .read = { ehci_mem_readb, ehci_mem_readw, ehci_mem_readl }, ! 2170: .write = { ehci_mem_writeb, ehci_mem_writew, ehci_mem_writel }, ! 2171: }, ! 2172: .endianness = DEVICE_LITTLE_ENDIAN, ! 2173: }; ! 2174: ! 2175: static int usb_ehci_initfn(PCIDevice *dev); ! 2176: ! 2177: static USBPortOps ehci_port_ops = { ! 2178: .attach = ehci_attach, ! 2179: .detach = ehci_detach, ! 2180: .child_detach = ehci_child_detach, ! 2181: .wakeup = ehci_wakeup, ! 2182: .complete = ehci_async_complete_packet, ! 2183: }; ! 2184: ! 2185: static USBBusOps ehci_bus_ops = { ! 2186: .register_companion = ehci_register_companion, ! 2187: }; ! 2188: ! 2189: static const VMStateDescription vmstate_ehci = { ! 2190: .name = "ehci", ! 2191: .unmigratable = 1, ! 2192: }; ! 2193: ! 2194: static Property ehci_properties[] = { ! 2195: DEFINE_PROP_UINT32("freq", EHCIState, freq, FRAME_TIMER_FREQ), ! 2196: DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128), ! 2197: DEFINE_PROP_END_OF_LIST(), ! 2198: }; ! 2199: ! 2200: static void ehci_class_init(ObjectClass *klass, void *data) ! 2201: { ! 2202: DeviceClass *dc = DEVICE_CLASS(klass); ! 2203: PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ! 2204: ! 2205: k->init = usb_ehci_initfn; ! 2206: k->vendor_id = PCI_VENDOR_ID_INTEL; ! 2207: k->device_id = PCI_DEVICE_ID_INTEL_82801D; /* ich4 */ ! 2208: k->revision = 0x10; ! 2209: k->class_id = PCI_CLASS_SERIAL_USB; ! 2210: dc->vmsd = &vmstate_ehci; ! 2211: dc->props = ehci_properties; ! 2212: } ! 2213: ! 2214: static TypeInfo ehci_info = { ! 2215: .name = "usb-ehci", ! 2216: .parent = TYPE_PCI_DEVICE, ! 2217: .instance_size = sizeof(EHCIState), ! 2218: .class_init = ehci_class_init, ! 2219: }; ! 2220: ! 2221: static void ich9_ehci_class_init(ObjectClass *klass, void *data) ! 2222: { ! 2223: DeviceClass *dc = DEVICE_CLASS(klass); ! 2224: PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ! 2225: ! 2226: k->init = usb_ehci_initfn; ! 2227: k->vendor_id = PCI_VENDOR_ID_INTEL; ! 2228: k->device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1; ! 2229: k->revision = 0x03; ! 2230: k->class_id = PCI_CLASS_SERIAL_USB; ! 2231: dc->vmsd = &vmstate_ehci; ! 2232: dc->props = ehci_properties; ! 2233: } ! 2234: ! 2235: static TypeInfo ich9_ehci_info = { ! 2236: .name = "ich9-usb-ehci1", ! 2237: .parent = TYPE_PCI_DEVICE, ! 2238: .instance_size = sizeof(EHCIState), ! 2239: .class_init = ich9_ehci_class_init, ! 2240: }; ! 2241: ! 2242: static int usb_ehci_initfn(PCIDevice *dev) ! 2243: { ! 2244: EHCIState *s = DO_UPCAST(EHCIState, dev, dev); ! 2245: uint8_t *pci_conf = s->dev.config; ! 2246: int i; ! 2247: ! 2248: pci_set_byte(&pci_conf[PCI_CLASS_PROG], 0x20); ! 2249: ! 2250: /* capabilities pointer */ ! 2251: pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x00); ! 2252: //pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x50); ! 2253: ! 2254: pci_set_byte(&pci_conf[PCI_INTERRUPT_PIN], 4); /* interrupt pin D */ ! 2255: pci_set_byte(&pci_conf[PCI_MIN_GNT], 0); ! 2256: pci_set_byte(&pci_conf[PCI_MAX_LAT], 0); ! 2257: ! 2258: // pci_conf[0x50] = 0x01; // power management caps ! 2259: ! 2260: pci_set_byte(&pci_conf[USB_SBRN], USB_RELEASE_2); // release number (2.1.4) ! 2261: pci_set_byte(&pci_conf[0x61], 0x20); // frame length adjustment (2.1.5) ! 2262: pci_set_word(&pci_conf[0x62], 0x00); // port wake up capability (2.1.6) ! 2263: ! 2264: pci_conf[0x64] = 0x00; ! 2265: pci_conf[0x65] = 0x00; ! 2266: pci_conf[0x66] = 0x00; ! 2267: pci_conf[0x67] = 0x00; ! 2268: pci_conf[0x68] = 0x01; ! 2269: pci_conf[0x69] = 0x00; ! 2270: pci_conf[0x6a] = 0x00; ! 2271: pci_conf[0x6b] = 0x00; // USBLEGSUP ! 2272: pci_conf[0x6c] = 0x00; ! 2273: pci_conf[0x6d] = 0x00; ! 2274: pci_conf[0x6e] = 0x00; ! 2275: pci_conf[0x6f] = 0xc0; // USBLEFCTLSTS ! 2276: ! 2277: // 2.2 host controller interface version ! 2278: s->mmio[0x00] = (uint8_t) OPREGBASE; ! 2279: s->mmio[0x01] = 0x00; ! 2280: s->mmio[0x02] = 0x00; ! 2281: s->mmio[0x03] = 0x01; // HC version ! 2282: s->mmio[0x04] = NB_PORTS; // Number of downstream ports ! 2283: s->mmio[0x05] = 0x00; // No companion ports at present ! 2284: s->mmio[0x06] = 0x00; ! 2285: s->mmio[0x07] = 0x00; ! 2286: s->mmio[0x08] = 0x80; // We can cache whole frame, not 64-bit capable ! 2287: s->mmio[0x09] = 0x68; // EECP ! 2288: s->mmio[0x0a] = 0x00; ! 2289: s->mmio[0x0b] = 0x00; ! 2290: ! 2291: s->irq = s->dev.irq[3]; ! 2292: ! 2293: usb_bus_new(&s->bus, &ehci_bus_ops, &s->dev.qdev); ! 2294: for(i = 0; i < NB_PORTS; i++) { ! 2295: usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops, ! 2296: USB_SPEED_MASK_HIGH); ! 2297: s->ports[i].dev = 0; ! 2298: } ! 2299: ! 2300: s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s); ! 2301: QTAILQ_INIT(&s->aqueues); ! 2302: QTAILQ_INIT(&s->pqueues); ! 2303: ! 2304: qemu_register_reset(ehci_reset, s); ! 2305: ! 2306: memory_region_init_io(&s->mem, &ehci_mem_ops, s, "ehci", MMIO_SIZE); ! 2307: pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); ! 2308: ! 2309: return 0; ! 2310: } ! 2311: ! 2312: static void ehci_register_types(void) ! 2313: { ! 2314: type_register_static(&ehci_info); ! 2315: type_register_static(&ich9_ehci_info); ! 2316: } ! 2317: ! 2318: type_init(ehci_register_types) ! 2319: ! 2320: /* ! 2321: * vim: expandtab ts=4 ! 2322: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.