This 3-part patch adds support for the big-endian OHCI implementations
found on IBM's stb04xxx and Freescale's MPC52xx processors.

Patch 1 Removes byteswapped OHCI constants in preparation for
        dynamically handling endianness.

Patch 2 Adds support for big-endian OHCI controllers.
        This is done primarily by applying the following transforms
        when dealing with controller data:
                ohci_readl(p)   --> ohci_read(ohci, p)
                writel(v, p)    --> ohci_writel(ohci, v, p)
                cpu_to_le16(v)  --> cpu_to_ohci16(ohci, v)
                cpu_to_le16p(v) --> cpu_to_ohci16p(ohci, v)
                cpu_to_le32(v)  --> cpu_to_ohci32(ohci, v)
                cpu_to_le32p(v) --> cpu_to_ohci32p(ohci, v)
                le16_to_cpu(v)  --> ohci16_to_cpu(ohci, v)
                le16_to_cpup(v) --> ohci16_to_cpup(ohci, v)
                le32_to_cpu(v)  --> ohci32_to_cpu(ohci, v)
                le32_to_cpup(v) --> ohci32_to_cpup(ohci, v)

        A bit in the flags field of struct ohci_hcd, OHCI_BIG_ENDIAN,
        enables the the transformed functions to support both
        big-endian and little-endian controllers at runtime, if needed.

Patch 3 Adds support for ohci controllers (big-endian) on STB04xxx and MPC52xx

Signed-off-by: Dale Farnsworth <[EMAIL PROTECTED]>

diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
--- a/drivers/usb/host/ohci.h   2004-08-02 13:30:26 -07:00
+++ b/drivers/usb/host/ohci.h   2004-08-02 13:30:26 -07:00
@@ -15,20 +15,20 @@
  * both EHCI and UHCI call similar structures a "QH".
  */
 struct ed {
-       /* first fields are hardware-specified, le32 */
+       /* first fields are hardware-specified */
        __u32                   hwINFO;         /* endpoint config bitmap */
        /* info bits defined by hcd */
-#define ED_DEQUEUE     __constant_cpu_to_le32(1 << 27)
+#define ED_DEQUEUE     (1 << 27)
        /* info bits defined by the hardware */
-#define ED_ISO         __constant_cpu_to_le32(1 << 15)
-#define ED_SKIP                __constant_cpu_to_le32(1 << 14)
-#define ED_LOWSPEED    __constant_cpu_to_le32(1 << 13)
-#define ED_OUT         __constant_cpu_to_le32(0x01 << 11)
-#define ED_IN          __constant_cpu_to_le32(0x02 << 11)
+#define ED_ISO         (1 << 15)
+#define ED_SKIP                (1 << 14)
+#define ED_LOWSPEED    (1 << 13)
+#define ED_OUT         (0x01 << 11)
+#define ED_IN          (0x02 << 11)
        __u32                   hwTailP;        /* tail of TD list */
        __u32                   hwHeadP;        /* head of TD list (hc r/w) */
-#define ED_C           __constant_cpu_to_le32(0x02)    /* toggle carry */
-#define ED_H           __constant_cpu_to_le32(0x01)    /* halted */
+#define ED_C           0x02                    /* toggle carry */
+#define ED_H           0x01                    /* halted */
        __u32                   hwNextED;       /* next ED in list */
 
        /* rest are purely for the driver's use */
@@ -70,7 +70,7 @@
  * and 4.3.2 (iso)
  */
 struct td {
-       /* first fields are hardware-specified, le32 */
+       /* first fields are hardware-specified */
        __u32           hwINFO;         /* transfer info bitmask */
 
        /* hwINFO bits for both general and iso tds: */
diff -Nru a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
--- a/drivers/usb/host/ohci-dbg.c       2004-08-02 13:30:26 -07:00
+++ b/drivers/usb/host/ohci-dbg.c       2004-08-02 13:30:26 -07:00
@@ -336,7 +336,7 @@
 ohci_dump_ed (const struct ohci_hcd *ohci, const char *label,
                const struct ed *ed, int verbose)
 {
-       u32     tmp = ed->hwINFO;
+       u32     tmp = le32_to_cpu (ed->hwINFO);
        char    *type = "";
 
        ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x\n",
@@ -349,19 +349,20 @@
        /* else from TDs ... control */
        }
        ohci_dbg (ohci,
-               "  info %08x MAX=%d%s%s%s%s EP=%d%s DEV=%d\n", le32_to_cpu (tmp),
-               0x03ff & (le32_to_cpu (tmp) >> 16),
+               "  info %08x MAX=%d%s%s%s%s EP=%d%s DEV=%d\n", tmp,
+               0x03ff & (tmp >> 16),
                (tmp & ED_DEQUEUE) ? " DQ" : "",
                (tmp & ED_ISO) ? " ISO" : "",
                (tmp & ED_SKIP) ? " SKIP" : "",
                (tmp & ED_LOWSPEED) ? " LOW" : "",
-               0x000f & (le32_to_cpu (tmp) >> 7),
+               0x000f & (tmp >> 7),
                type,
-               0x007f & le32_to_cpu (tmp));
+               0x007f & tmp);
+       tmp = le32_to_cpup (&ed->hwHeadP);
        ohci_dbg (ohci, "  tds: head %08x %s%s tail %08x%s\n",
-               tmp = le32_to_cpup (&ed->hwHeadP),
-               (ed->hwHeadP & ED_C) ? data1 : data0,
-               (ed->hwHeadP & ED_H) ? " HALT" : "",
+               tmp,
+               (tmp & ED_C) ? data1 : data0,
+               (tmp & ED_H) ? " HALT" : "",
                le32_to_cpup (&ed->hwTailP),
                verbose ? "" : " (not listing)");
        if (verbose) {
@@ -415,8 +416,9 @@
 
        /* dump a snapshot of the bulk or control schedule */
        while (ed) {
-               u32                     info = ed->hwINFO;
+               u32                     info = le32_to_cpu (ed->hwINFO);
                u32                     scratch = cpu_to_le32p (&ed->hwINFO);
+               u32                     scratch2 = cpu_to_le32 (ed->hwHeadP);
                struct list_head        *entry;
                struct td               *td;
 
@@ -430,8 +432,8 @@
                        0x03ff & (scratch >> 16),
                        scratch,
                        (info & ED_SKIP) ? " s" : "",
-                       (ed->hwHeadP & ED_H) ? " H" : "",
-                       (ed->hwHeadP & ED_C) ? data1 : data0);
+                       (scratch2 & ED_H) ? " H" : "",
+                       (scratch2 & ED_C) ? data1 : data0);
                size -= temp;
                buf += temp;
 
@@ -541,7 +543,7 @@
 
                        /* show more info the first time around */
                        if (temp == seen_count) {
-                               u32     info = ed->hwINFO;
+                               u32     info = ohci32_to_cpu(ohci, ed->hwINFO);
                                u32     scratch = cpu_to_le32p (&ed->hwINFO);
                                struct list_head        *entry;
                                unsigned                qlen = 0;
@@ -562,7 +564,8 @@
                                        0x03ff & (scratch >> 16),
                                        scratch,
                                        (info & ED_SKIP) ? " K" : "",
-                                       (ed->hwHeadP & ED_H) ? " H" : "");
+                                       (le32_to_cpu(ed->hwHeadP) &
+                                        ED_H) ? " H" : "");
                                size -= temp;
                                next += temp;
 
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c       2004-08-02 13:30:26 -07:00
+++ b/drivers/usb/host/ohci-hcd.c       2004-08-02 13:30:26 -07:00
@@ -730,7 +730,7 @@
                switch (ed->state) {
                case ED_OPER:
                        ed->state = ED_UNLINK;
-                       ed->hwINFO |= ED_DEQUEUE;
+                       ed->hwINFO |= cpu_to_le32(ED_DEQUEUE);
                        ed_deschedule (ohci, ed);
 
                        ed->ed_next = ohci->ed_rm_list;
diff -Nru a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
--- a/drivers/usb/host/ohci-mem.c       2004-08-02 13:30:26 -07:00
+++ b/drivers/usb/host/ohci-mem.c       2004-08-02 13:30:26 -07:00
@@ -120,7 +120,7 @@
                prev = &(*prev)->td_hash;
        if (*prev)
                *prev = td->td_hash;
-       else if ((td->hwINFO & TD_DONE) != 0)
+       else if ((le32_to_cpu(td->hwINFO) & TD_DONE) != 0)
                ohci_dbg (hc, "no hash for td %p\n", td);
        dma_pool_free (hc->td_cache, td, td->td_dma);
 }
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c 2004-08-02 13:30:26 -07:00
+++ b/drivers/usb/host/ohci-q.c 2004-08-02 13:30:26 -07:00
@@ -131,7 +131,7 @@
        unsigned        i;
 
        ohci_vdbg (ohci, "link %sed %p branch %d [%dus.], interval %d\n",
-               (ed->hwINFO & ED_ISO) ? "iso " : "",
+               (ed->hwINFO & cpu_to_le32 (ED_ISO)) ? "iso " : "",
                ed, ed->branch, ed->load, ed->interval);
 
        for (i = ed->branch; i < NUM_INTS; i += ed->interval) {
@@ -272,7 +272,7 @@
        hcd_to_bus (&ohci->hcd)->bandwidth_allocated -= ed->load / ed->interval;
 
        ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n",
-               (ed->hwINFO & ED_ISO) ? "iso " : "",
+               (ed->hwINFO & cpu_to_le32 (ED_ISO)) ? "iso " : "",
                ed, ed->branch, ed->load, ed->interval);
 }
 
@@ -300,7 +300,7 @@
  */
 static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) 
 {
-       ed->hwINFO |= ED_SKIP;
+       ed->hwINFO |= cpu_to_le32 (ED_SKIP);
        wmb ();
        ed->state = ED_UNLINK;
 
@@ -433,14 +433,14 @@
                info |= usb_maxpacket (udev, pipe, is_out) << 16;
                info = cpu_to_le32 (info);
                if (udev->speed == USB_SPEED_LOW)
-                       info |= ED_LOWSPEED;
+                       info |= cpu_to_le32 (ED_LOWSPEED);
                /* only control transfers store pids in tds */
                if (type != PIPE_CONTROL) {
-                       info |= is_out ? ED_OUT : ED_IN;
+                       info |= cpu_to_le32(is_out ? ED_OUT : ED_IN);
                        if (type != PIPE_BULK) {
                                /* periodic transfers... */
                                if (type == PIPE_ISOCHRONOUS)
-                                       info |= ED_ISO;
+                                       info |= cpu_to_le32 (ED_ISO);
                                else if (interval > 32) /* iso can be bigger */
                                        interval = 32;
                                ed->interval = interval;
@@ -469,7 +469,7 @@
  */
 static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed)
 {    
-       ed->hwINFO |= ED_DEQUEUE;
+       ed->hwINFO |= cpu_to_le32 (ED_DEQUEUE);
        ed_deschedule (ohci, ed);
 
        /* rm_list is just singly linked, for simplicity */
@@ -593,7 +593,7 @@
        if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) {
                usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe),
                        is_out, 1);
-               urb_priv->ed->hwHeadP &= ~ED_C;
+               urb_priv->ed->hwHeadP &= ~cpu_to_le32 (ED_C);
        }
 
        urb_priv->td_cnt = 0;
@@ -795,14 +795,14 @@
        struct urb              *urb = td->urb;
        struct ed               *ed = td->ed;
        struct list_head        *tmp = td->td_list.next;
-       u32                     toggle = ed->hwHeadP & ED_C;
+       u32                     toggle = ed->hwHeadP & cpu_to_ohci32 (ED_C);
 
        /* clear ed halt; this is the td that caused it, but keep it inactive
         * until its urb->complete() has a chance to clean up.
         */
-       ed->hwINFO |= ED_SKIP;
+       ed->hwINFO |= cpu_to_le32 (ED_SKIP);
        wmb ();
-       ed->hwHeadP &= ~ED_H; 
+       ed->hwHeadP &= ~cpu_to_le32 (ED_H); 
 
        /* put any later tds from this urb onto the donelist, after 'td',
         * order won't matter here: no errors, and nothing was transferred.
@@ -894,7 +894,8 @@
                 * and dequeue any other TDs from this urb.
                 * No other TD could have caused the halt.
                 */
-               if (cc != TD_CC_NOERROR && (td->ed->hwHeadP & ED_H))
+               if (cc != TD_CC_NOERROR &&
+                               (td->ed->hwHeadP & cpu_to_le32 (ED_H)))
                        td_rev = ed_halted (ohci, td, cc, td_rev);
 
                td->next_dl_td = td_rev;        
@@ -998,10 +999,10 @@
 
                /* ED's now officially unlinked, hc doesn't see */
                ed->state = ED_IDLE;
-               ed->hwHeadP &= ~ED_H;
+               ed->hwHeadP &= ~cpu_to_le32(ED_H);
                ed->hwNextED = 0;
                wmb ();
-               ed->hwINFO &= ~(ED_SKIP | ED_DEQUEUE);
+               ed->hwINFO &= ~cpu_to_le32 (ED_SKIP | ED_DEQUEUE);
 
                /* but if there's work queued, reschedule */
                if (!list_empty (&ed->td_list)) {
@@ -1080,10 +1081,10 @@
                                start_ed_unlink (ohci, ed);
 
                /* ... reenabling halted EDs only after fault cleanup */
-               } else if ((ed->hwINFO & (ED_SKIP | ED_DEQUEUE)) == ED_SKIP) {
+               } else if ((ed->hwINFO & cpu_to_le32 (ED_SKIP | ED_DEQUEUE)) == 
cpu_to_le32 (ED_SKIP)) {
                        td = list_entry (ed->td_list.next, struct td, td_list);
                        if (!(td->hwINFO & TD_DONE)) {
-                               ed->hwINFO &= ~ED_SKIP;
+                               ed->hwINFO &= ~cpu_to_le32 (ED_SKIP);
                                /* ... hc may need waking-up */
                                switch (ed->type) {
                                case PIPE_CONTROL:


-------------------------------------------------------
This SF.Net email is sponsored by OSTG. Have you noticed the changes on
Linux.com, ITManagersJournal and NewsForge in the past few weeks? Now,
one more big change to announce. We are now OSTG- Open Source Technology
Group. Come see the changes on the new OSTG site. www.ostg.com
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to