Annotation of qemu/hw/usb/hcd-ehci.c, revision 1.1

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:  */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.