Patchwork [01/22] xhci: add {get, set}_field macros & enum for pls

login
register
mail settings
Submitter Gerd Hoffmann
Date Oct. 30, 2012, 2:26 p.m.
Message ID <1351607214-4007-2-git-send-email-kraxel@redhat.com>
Download mbox | patch
Permalink /patch/195519/
State New
Headers show

Comments

Gerd Hoffmann - Oct. 30, 2012, 2:26 p.m.
Add {get,set}_field macros (simliar to ehci) to read and update
some bits of a word.  Put them into use for updating pls (port
link state) values.  Also add a enum for pls values.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |   39 +++++++++++++++++++++++++++++++--------
 1 files changed, 31 insertions(+), 8 deletions(-)

Patch

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 7b65741..c062330 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -146,6 +146,21 @@  typedef struct XHCITRB {
     bool ccs;
 } XHCITRB;
 
+enum {
+    PLS_U0              =  0,
+    PLS_U1              =  1,
+    PLS_U2              =  2,
+    PLS_U3              =  3,
+    PLS_DISABLED        =  4,
+    PLS_RX_DETECT       =  5,
+    PLS_INACTIVE        =  6,
+    PLS_POLLING         =  7,
+    PLS_RECOVERY        =  8,
+    PLS_HOT_RESET       =  9,
+    PLS_COMPILANCE_MODE = 10,
+    PLS_TEST_MODE       = 11,
+    PLS_RESUME          = 15,
+};
 
 typedef enum TRBType {
     TRB_RESERVED = 0,
@@ -287,6 +302,16 @@  typedef enum TRBCCode {
 
 typedef struct XHCIState XHCIState;
 
+#define get_field(data, field)                  \
+    (((data) >> field##_SHIFT) & field##_MASK)
+
+#define set_field(data, newval, field) do {                     \
+        uint32_t val = *data;                                   \
+        val &= ~(field##_MASK << field##_SHIFT);                \
+        val |= ((newval) & field##_MASK) << field##_SHIFT;      \
+        *data = val;                                            \
+    } while (0)
+
 typedef enum EPType {
     ET_INVALID = 0,
     ET_ISO_OUT,
@@ -2334,7 +2359,7 @@  static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach)
         }
     }
 
-    if (xhci_running(xhci)) {
+    if (xhci_running(port->xhci)) {
         port->portsc |= PORTSC_CSC;
         XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS,
                          port->portnr << 24};
@@ -2368,7 +2393,7 @@  static void xhci_reset(DeviceState *dev)
     }
 
     for (i = 0; i < xhci->numports; i++) {
-        xhci_update_port(xhci, xhci->ports + i, 0);
+        xhci_update_port(xhci->ports + i, 0);
     }
 
     for (i = 0; i < xhci->numintrs; i++) {
@@ -2499,8 +2524,8 @@  static void xhci_port_write(void *ptr, hwaddr reg,
                            PORTSC_PRC|PORTSC_PLC|PORTSC_CEC));
         if (val & PORTSC_LWS) {
             /* overwrite PLS only when LWS=1 */
-            portsc &= ~(PORTSC_PLS_MASK << PORTSC_PLS_SHIFT);
-            portsc |= val & (PORTSC_PLS_MASK << PORTSC_PLS_SHIFT);
+            uint32_t pls = get_field(val, PORTSC_PLS);
+            set_field(&portsc, pls, PORTSC_PLS);
         }
         /* read/write bits */
         portsc &= ~(PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE);
@@ -2832,13 +2857,11 @@  static void xhci_wakeup(USBPort *usbport)
     XHCIPort *port = xhci_lookup_port(xhci, usbport);
     XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS,
                      port->portnr << 24};
-    uint32_t pls;
 
-    pls = (port->portsc >> PORTSC_PLS_SHIFT) & PORTSC_PLS_MASK;
-    if (pls != 3) {
+    if (get_field(port->portsc, PORTSC_PLS) != PLS_U3) {
         return;
     }
-    port->portsc |= 0xf << PORTSC_PLS_SHIFT;
+    set_field(&port->portsc, PLS_RESUME, PORTSC_PLS);
     if (port->portsc & PORTSC_PLC) {
         return;
     }