Hi,

> I looked through the ohci-isp1362.h (thanks Dimitris for
> forwarding it) and compared the register layout with the one
> needed for 1160. Indeed the match is very good and it would
> suffice to add the definitions of just few registers (0x2d,
> 0x2e, and 0x41) to cover also 1160. Didn't make bit
> comparisons of registers though.
> 
> Lothar, a little bugfix: the macro __isp1362_clr_mask16()
> currently sets rather than clears.
> 
Thanks for that one. Usual copy/paste error. Since I still don't have
any hardware to run this code on I didn't have the chance to notice it
yet. :(

I've had a look through the code during the weekend and made some
updates:
- Depending on the hardware you have you may or may not need to split
  up 32 bit register accesses into two 16bit accesses to the same
  address. '#define CAN_USE_32BIT 0' takes care of this
- fixed some typos 
- the read/write_buffer function takes care of buffer alignment and
  should handle leading/trailing bytes correctly. At least on the 1362
  that has "Direct Adress" mode to access the internal buffers.
 
I also fixed some bugs in the SL811 code:
- the page wrap wasn't handled correctly


Lothar Wassmann
--- linux-2.6.8.1/drivers/usb/host/ohci-isp1362.h       2004-09-13 19:26:23.000000000 
+0200
+++ linux-2.6.8.1-karo/drivers/usb/host/ohci-isp1362.h  2004-09-13 15:40:46.000000000 
+0200
@@ -13,7 +13,7 @@
 #endif
 
 // settings used for debugging:
-#define DEBUG
+//#define DEBUG
 #ifdef DEBUG
 #define BUFFER_TEST
 #define TEST_BUF_SIZE  4096
@@ -33,7 +33,6 @@
 #define REG_ACCESS_M   0x800           // reg needs to be merged with shadow reg
 #define REG_ACCESS_MASK        0x600
 
-//#define PTD_BLK_SIZE 64
 #define ISP1362_BUF_SIZE               4096
 #define ISP1362_REG_WRITE_OFFSET       0x80
 
@@ -102,13 +101,13 @@
 ISP1362_REG(HCDMACFG,  0x21,   REG_WIDTH_16,   REG_ACCESS_RW);
 #define HCDMACFG_CTR_ENABLE    (1 << 7)
 #define HCDMACFG_BURST_LEN_MASK        (0x03 << 5)
-#define HCDMACFG_BURST_LEN(n)  (((n) << 5) & HCDMACFG_BURST_LEN__MASK)
+#define HCDMACFG_BURST_LEN(n)  (((n) << 5) & HCDMACFG_BURST_LEN_MASK)
 #define HCDMACFG_BURST_LEN_1   HCDMACFG_BURST_LEN(0)
 #define HCDMACFG_BURST_LEN_4   HCDMACFG_BURST_LEN(1)
 #define HCDMACFG_BURST_LEN_8   HCDMACFG_BURST_LEN(2)
 #define HCDMACFG_DMA_ENABLE    (1 << 4)
 #define HCDMACFG_BUF_TYPE_MASK (0x07 << 1)
-#define HCDMACFG_BUF_TYPE(n)   (((n) << 1) & HCDMACFG_BURST_LEN__MASK)
+#define HCDMACFG_BUF_TYPE(n)   (((n) << 1) & HCDMACFG_BUF_TYPE_MASK)
 #define HCDMACFG_BUF_ISTL0     HCDMACFG_BUF_TYPE(0)
 #define HCDMACFG_BUF_ISTL1     HCDMACFG_BUF_TYPE(1)
 #define HCDMACFG_BUF_INTL      HCDMACFG_BUF_TYPE(2)
@@ -201,6 +200,11 @@
                                 HCHWCFG_DBWIDTH(1) |           \
                                 HCHWCFG_INT_POL |              \
                                 HCHWCFG_INT_ENABLE)
+
+#define HCDMACFG_INIT_VAL      (HCDMACFG_BUF_DIRECT | HCDMACFG_BURST_LEN_4)
+
+#define CAN_USE_32BIT  1
+
 #else
 #error Specify appropriate initialization values for HW configuration registers
 #define HCHWCFG_INIT_VAL       ()
@@ -280,7 +284,7 @@
        int             xfer_type:2;
        int             port:1;
        u16             buf_addr;
-//     int             buf_len;
+       int             buf_len;
 } __attribute__((packed));
 
 struct ptd_queue {
@@ -352,53 +356,63 @@
 #define hc_isp1362_data_reg (dev->data_reg)
 
 // basic access functions for ISP1362 chip registers
+/* NOTE: The contents of the command register cannot read back! The driver must 
ensure,
+ * that all register accesses are performed with interrupts disabled, since the 
interrupt
+ * handler has no way of restoring the previous state.
+ */
 static inline void HC_ISP1362_WRITE_ADDR(struct hc_isp1362_dev *dev, isp1362_reg_t 
reg)
 {
        //DDPRINTK("A>[EMAIL PROTECTED]", reg, (u32)hc_isp1362_addr_reg);
-       __asm__ volatile ("/* HC_ISP1362_WRITE_ADDR START */");
-       _BUG_ON((reg & 0x80) && !(reg & REG_ACCESS_W));
+       _BUG_ON((reg & ISP1362_REG_WRITE_OFFSET) && !(reg & REG_ACCESS_W));
+       _BUG_ON(!irqs_disabled());
        writew(reg, hc_isp1362_addr_reg);
-       __asm__ volatile ("/* HC_ISP1362_WRITE_ADDR END */");
 }
 
 static inline void HC_ISP1362_WRITE_DATA16(struct hc_isp1362_dev *dev, u16 val)
 {
-       __asm__ volatile ("/* HC_ISP1362_WRITE_DATA16 START */");
        writew(val, hc_isp1362_data_reg);
-       __asm__ volatile ("/* HC_ISP1362_WRITE_DATA16 END */");
 }
 
 static inline u16 HC_ISP1362_READ_DATA16(struct hc_isp1362_dev *dev)
 {
        u16 val;
 
-       __asm__ volatile ("/* HC_ISP1362_READ_DATA16 START */");
+       _BUG_ON(!irqs_disabled());
        val = readw(hc_isp1362_data_reg);
        //DDPRINTK("D<[EMAIL PROTECTED]", val, (u32)hc_isp1362_data_reg);
 
-       __asm__ volatile ("/* HC_ISP1362_READ_DATA16 END */");
        return val;
 }
 
 static inline void HC_ISP1362_WRITE_DATA32(struct hc_isp1362_dev *dev, u32 val)
 {
-       __asm__ volatile ("/* HC_ISP1362_WRITE_DATA32 START */");
+       _BUG_ON(!irqs_disabled());
+#if CAN_USE_32BIT
        writel(val, hc_isp1362_data_reg);
-       __asm__ volatile ("/* HC_ISP1362_WRITE_DATA32 END */");
+#else
+       writew((u16)val, hc_isp1362_data_reg);
+       writew((u16)(val >> 16), hc_isp1362_data_reg);
+#endif
 }
 
 static inline u32 HC_ISP1362_READ_DATA32(struct hc_isp1362_dev *dev)
 {
        u32 val;
 
-       __asm__ volatile ("/* HC_ISP1362_READ_DATA32 START */");
+       _BUG_ON(!irqs_disabled());
+#if CAN_USE_32BIT
        val = readl(hc_isp1362_data_reg);
+#else
+       val = (u32)readw(hc_isp1362_data_reg);
+       val |= (u32)readw(hc_isp1362_data_reg) << 16;
+#endif
        //DDPRINTK("D<[EMAIL PROTECTED]", val, (u32)hc_isp1362_data_reg);
-
-       __asm__ volatile ("/* HC_ISP1362_READ_DATA32 END */");
        return val;
 }
 
+// The register access routines '__isp1362_...' require interrupts to be disabled
+// upon entering the routine
+// The routines 'isp1362_...' disable interrupts before register access
 #define __isp1362_read_reg16(d, r)             ({                      \
        u16 __v;                                                        \
        _BUG_ON(((ISP1362_REG_##r) & REG_WIDTH_MASK) != REG_WIDTH_16);  \
@@ -441,51 +455,6 @@
        local_irq_restore(flags);       \
 }
 
-#if 0
-// access functions for ISP1362 specific (16bit) registers
-static inline u16 __hc_isp1362_read_reg(struct hc_isp1362_dev *dev, isp1362_reg_t reg)
-{
-       u16 val;
-
-       __asm__ volatile ("/* __hc_isp1362_read_reg START */");
-       _BUG_ON((reg & REG_WIDTH_MASK) != REG_WIDTH_16);
-       HC_ISP1362_WRITE_ADDR(dev, reg);
-       val = HC_ISP1362_READ_DATA16(dev);
-       __asm__ volatile ("/* __hc_isp1362_read_reg END */");
-       return val;
-}
-
-static inline u16 hc_isp1362_read_reg(struct hc_isp1362_dev *dev, isp1362_reg_t reg)
-{
-       u16 val;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       val = __hc_isp1362_read_reg(dev, reg);
-       local_irq_restore(flags);
-
-       return val;
-}
-
-static inline void __hc_isp1362_write_reg(struct hc_isp1362_dev *dev, isp1362_reg_t 
reg, u16 val)
-{
-       __asm__ volatile ("/* __hc_isp1362_write_reg START */");
-       _BUG_ON((reg & REG_WIDTH_MASK) != REG_WIDTH_16);
-       HC_ISP1362_WRITE_ADDR(dev, reg | ISP1362_REG_WRITE_OFFSET);
-       HC_ISP1362_WRITE_DATA16(dev, val);
-       __asm__ volatile ("/* __hc_isp1362_write_reg END */");
-}
-
-static inline void hc_isp1362_write_reg(struct hc_isp1362_dev *dev, isp1362_reg_t 
reg, u16 val)
-{
-       unsigned long flags;
-
-       local_irq_save(flags);
-       __hc_isp1362_write_reg(dev, reg, val);
-       local_irq_restore(flags);
-}
-#endif
-
 #define __isp1362_set_mask16(d,r,m) {          \
        u16 __v;                                \
        __v = __isp1362_read_reg16(dev, r);     \
@@ -504,9 +473,10 @@
 #define __isp1362_clr_mask16(d,r,m) {          \
        u16 __v;                                \
        __v = __isp1362_read_reg16(dev, r);     \
-       __v |= m;                               \
+       __v &= ~(m);                            \
        __isp1362_write_reg16(dev, r, __v);     \
 }
+
 #define isp1362_clr_mask16(d,r,m) {    \
        unsigned long flags;            \
                                        \
@@ -515,20 +485,58 @@
        local_irq_restore(flags);       \
 }
 
-static inline int __isp1362_read_buffer(struct hc_isp1362_dev *dev, void *buf, u16 
offset, u16 len)
+static inline void __isp1362_dma_enable(struct hc_isp1362_dev *dev, int write)
+{
+       __isp1362_set_mask16(dev, HCuPINT, HCuPINT_EOT);
+       __isp1362_set_mask16(dev, HCDMACFG, HCDMACFG_DMA_ENABLE | (write ? 
HCDMACFG_DMA_RW_SELECT : 0));
+}
+
+static inline void __isp1362_dma_disable(struct hc_isp1362_dev *dev)
+{
+       __isp1362_clr_mask16(dev, HCuPINT, HCuPINT_EOT);
+       __isp1362_clr_mask16(dev, HCDMACFG, HCDMACFG_DMA_ENABLE);
+}
+
+static inline int __isp1362_read_buffer(struct hc_isp1362_dev *dev, void *buf, u16 
offset, int len)
 {
        int ret;
        u8 *dp = buf;
        u16 data;
-       int i;
 
+#if 1
+       // need to check, that unaligned offset & len is ok
        __isp1362_write_reg32(dev, HCDIRADDR, HCDIRADDR_ADDR(offset) | 
HCDIRADDR_COUNT(len));
-       for (i = 0; i < len - 1; i += 2) {
-               data = __isp1362_read_reg16(dev, HCDIRDATA);
-               *dp++ = data;
-               *dp++ = data >> 8;
+#else
+       __isp1362_write_reg32(dev, HCDIRADDR, HCDIRADDR_ADDR(offset & ~1) |
+                             HCDIRADDR_COUNT((len + (len & 1) + (offset & 1) & ~1));
+#endif
+       if (offset & 1) {
+               // the address within the chip buffer is not 16bit aligned
+               // read the first unaligned byte, then do the aligned transfer.
+               *dp++ = (u8)(__isp1362_read_reg16(dev, HCDIRDATA) >> 8);
+               len--;
        }
-       if (len & 1) {
+
+       if (!((u32)dp & 1)) {
+               u16 *dp16 = (u16*)dp;
+               // buffer is 16bit aligned; can use 16bit aligned writes to memory
+               while (len > 1) {
+                       *dp16 = __isp1362_read_reg16(dev, HCDIRDATA);
+                       dp16++;
+                       len -= 2;
+               }
+               dp = (u8*)dp16;
+       } else {
+               while (len > 1) {
+                       data = __isp1362_read_reg16(dev, HCDIRDATA);
+                       *dp++ = (u8)data;
+                       *dp++ = (u8)(data >> 8);
+                       len -= 2;
+               }
+       }
+
+       WARN_ON(len & ~1);
+       if (len > 0) {
                data = __isp1362_read_reg16(dev, HCDIRDATA);
                *dp++ = data;
        }
@@ -536,21 +544,54 @@
        return ret;
 }
 
-static inline int __isp1362_write_buffer(struct hc_isp1362_dev *dev, void *buf, u16 
offset, u16 len)
+static inline int __isp1362_write_buffer(struct hc_isp1362_dev *dev, void *buf, u16 
offset, int len)
 {
        int ret;
        u8 *dp = buf;
        u16 data;
-       int i;
 
        __isp1362_write_reg32(dev, HCDIRADDR, HCDIRADDR_ADDR(offset) | 
HCDIRADDR_COUNT(len));
-       for (i = 0; i < len - 1; i += 2) {
-               data = *dp++;
-               data = (data << 8) | *dp++;
+
+       if (offset & 1) {
+               // the address within the chip buffer is not 16bit aligned
+               // write the first unaligned byte, then do the aligned transfer.
+               // In order not to disturb previously written data, we need to fetch 
the
+               // first word from the buffer and replace the high byte
+               data = __isp1362_read_reg16(dev, HCDIRDATA) & 0xff;
+               data |= *dp++;
+               // reset the direct address/count register
+               __isp1362_write_reg32(dev, HCDIRADDR, HCDIRADDR_ADDR(offset) | 
HCDIRADDR_COUNT(len));
+
+               // finally write the data word
                __isp1362_write_reg16(dev, HCDIRDATA, data);
+
+               len--;
        }
-       if (len & 1) {
-               data = *dp++;
+
+       if (!((u32)dp & 1)) {
+               u16 *dp16 = (u16*)dp;
+               // memory buffer is 16bit aligned; can read with word accesses
+               while (len > 1) {
+                       __isp1362_write_reg16(dev, HCDIRDATA, *dp16);
+                       dp16++;
+                       len -= 2;
+               }
+               dp = (u8*)dp16;
+       } else {
+               // memory buffer is not 16bit aligned; must use byte access
+               while (len > 1) {
+                       data = *dp++;
+                       data = (data << 8) | *dp++;
+                       __isp1362_write_reg16(dev, HCDIRDATA, data);
+                       len -= 2;
+               }
+       }
+
+       WARN_ON(len & ~1);
+       if (len > 0) {
+               // finally write any trailing byte; we don't need to care about the 
high byte of
+               // the last word written
+               data = (u16)*dp++;
                __isp1362_write_reg16(dev, HCDIRDATA, data);
        }
 
@@ -596,4 +637,4 @@
 #endif
 
 // function prototypes
-static __inline void retire_td(struct usb_hcd *hcd, struct td *td, struct ed *ed);
+static __inline void retire_td(struct usb_hcd *hcd, struct td *td, struct ed *ed, u32 
cc);
--- linux-2.6.8.1/drivers/usb/host/ohci-sl811-emu.c     2004-09-13 18:56:15.000000000 
+0200
+++ linux-2.6.8.1-karo/drivers/usb/host/ohci-sl811-emu.c        2004-09-13 
19:09:24.000000000 +0200
@@ -16,6 +16,8 @@
 
 #include <asm/arch/dma.h>
 
+#define MULT_CTRL
+
 #define get_hw_fld(p,n)                le32_to_cpu((p)->hw##n)
 #define set_hw_fld(p,n,v)      (p)->hw##n = cpu_to_le32(v)
 #define get_hwinfo(p)          get_hw_fld(p, INFO)
@@ -32,25 +34,27 @@
 #define TD_FC_GET(info)                (((info) >> 24) & 7)
 #define TD_SF_GET(info)                (((info) >> 0) & 0xffff)
 
-static u32 TD_BUF_LEN(struct td *td)
+static inline u32 BUF_LEN(u32 cbp, u32 be)
 {
-       u32 len = 0;
-       u32 cbp = get_hw_fld(td, CBP);
+       u32 len;
 
-       if (cbp != 0) {
-               u32 be = get_hw_fld(td, BE);
+       if (cbp == 0) {
+               return 0;
+       }
 
-               if (unlikely((cbp ^ be) & PAGE_MASK)) {
-                       // CBP and BE in different pages
-                       // length till end of first page  +  length in second page
-                       len = (PAGE_SIZE - (cbp & ~PAGE_MASK)) + (be & ~PAGE_MASK) + 1;
-               } else {
-                       len = be - cbp + 1;
-               }
+       if (unlikely((cbp ^ be) & PAGE_MASK)) {
+               // CBP and BE in different pages
+               // length till end of first page  +  length in second page
+               len = (PAGE_SIZE - (cbp & ~PAGE_MASK)) + (be & ~PAGE_MASK) + 1;
+       } else {
+               len = be - cbp + 1;
        }
+       BUG_ON(len > 2  * PAGE_SIZE);
 
        return len;
 }
+#define TD_BUF_LEN(td) BUF_LEN(get_hw_fld(td, CBP), get_hw_fld(td, BE))
+
 
 #define ED_MPS         (((1 << 10) - 1) << 16)
 #define ed_pid(info)   (((info) & (ED_IN | ED_OUT)) >> 11)
@@ -68,13 +72,9 @@
 
 static inline u32 DMA_XFER_SIZE(u32 addr, u32 len)
 {
-       u32 count = len;
+       u32 max_count = PAGE_SIZE - (addr & ~PAGE_MASK);
 
-       if (unlikely(((addr & ~PAGE_MASK) + len) > PAGE_SIZE)) {
-               count = PAGE_ALIGN(addr + len) - addr;
-       }
-
-       return count;
+       return len > max_count ? max_count : len;
 }
 
 #define OHCI_FR ((1 << 14) - 1)
@@ -98,8 +98,8 @@
        unsigned int time;
        unsigned int available = update_fm_remaining(ohci);
        struct ohci_regs *regs = ohci->regs;
-       struct usb_hcd *hcd = ohci_to_hcd(ohci);
-       struct hc_sl811_dev *dev = hcd_to_sl811_dev(hcd);
+       //struct usb_hcd *hcd = ohci_to_hcd(ohci);
+       //struct hc_sl811_dev *dev = hcd_to_sl811_dev(hcd);
 
        if (ed_flags & ED_LOWSPEED) {
                if (available < HcLsThreshold) {
@@ -135,37 +135,78 @@
        }
 }
 
+static u32 update_cbp(u32 cbp, u32 be, u32 len)
+{
+       unsigned int chunk_size = DMA_XFER_SIZE(cbp, len);
+
+       BUG_ON(chunk_size > len);
+       BUG_ON(chunk_size > BUF_LEN(cbp, be));
+
+       if (likely(chunk_size == len)) {
+               // all data fits in current page
+               cbp += len;
+       } else {
+               // data extends into next page
+               cbp = (be & PAGE_MASK) + (len - chunk_size);
+       }
+       if (cbp - 1 == be) {
+               // all data has been transferred for this TD
+               cbp = 0;
+       }
+
+       return cbp;
+}
+
 static void sl811_dma_recv_data(struct hc_sl811_dev *dev, struct xfer_buf *buf, u8 
offset)
 {
        struct usb_hcd *hcd = hc_sl811_dev_to_hcd(dev);
+       dma_addr_t dma_addr = buf->dma_addr;
+       int len = buf->count;
 
-       if (buf->count == 0) {
-               // nothing to to, if no transfer buffer given
-               return;
-       }
+       BUG_ON(len > buf->buf_len || len > (SL811_BUF_SIZE / FLIP_BUFFERS));
+
+       WARN_ON((dma_addr == 0) ^ (len == 0));
+       while (len > 0) {
+               u32 dma_size = DMA_XFER_SIZE(dma_addr, len);
+               void *buf_addr = (void*)dma_to_virt(hcd->self.controller, dma_addr);
 
-       BUG_ON(buf->count > buf->buf_len || buf->count > (SL811_BUF_SIZE / 
FLIP_BUFFERS));
-       BUG_ON(buf->buf_addr == NULL);
+               __hc_sl811_read_regs(dev, offset, buf_addr, dma_size);
+               dma_sync_single_for_device(hcd->self.controller, dma_addr, dma_size, 
DMA_TO_DEVICE);
 
-       __hc_sl811_read_regs(dev, offset, buf->buf_addr, buf->count);
-       dma_sync_single_for_cpu(hcd->self.controller, get_hw_fld(buf->td, CBP), 
buf->count,
-                               DMA_TO_DEVICE);
+               if (len == dma_size) {
+                       len = 0;
+               } else {
+                       dma_addr = get_hw_fld(buf->td, BE) & PAGE_MASK;
+                       len -= dma_size;
+                       offset += dma_size;
+               }
+       }
 }
 
 static void sl811_dma_send_data(struct hc_sl811_dev *dev, struct xfer_buf *buf, u8 
offset)
 {
        struct usb_hcd *hcd = hc_sl811_dev_to_hcd(dev);
+       dma_addr_t dma_addr = buf->dma_addr;
+       int len = buf->len;
 
-       if (buf->len == 0) {
-               // nothing to to, if no transfer buffer given
-               return;
-       }
+       BUG_ON(len > buf->buf_len || len > (SL811_BUF_SIZE / FLIP_BUFFERS));
+
+       WARN_ON((dma_addr == 0) ^ (len == 0));
+       while (len > 0) {
+               u32 dma_size = DMA_XFER_SIZE(dma_addr, len);
+               void *buf_addr = (void*)dma_to_virt(hcd->self.controller, dma_addr);
 
-       BUG_ON(buf->len > buf->buf_len || buf->len > (SL811_BUF_SIZE / FLIP_BUFFERS));
+               dma_sync_single_for_cpu(hcd->self.controller, dma_addr, dma_size, 
DMA_FROM_DEVICE);
+               __hc_sl811_write_regs(dev, offset, buf_addr, dma_size);
 
-       dma_sync_single_for_cpu(hcd->self.controller, get_hw_fld(buf->td, CBP), 
buf->len,
-                               DMA_FROM_DEVICE);
-       __hc_sl811_write_regs(dev, offset, buf->buf_addr, buf->len);
+               if (len == dma_size) {
+                       len = 0;
+               } else {
+                       dma_addr = get_hw_fld(buf->td, BE) & PAGE_MASK;
+                       len -= dma_size;
+                       offset += dma_size;
+               }
+       }
 }
 
 static int start_xfer(struct usb_hcd *hcd, struct hc_sl811_dev *dev, int flip)
@@ -193,11 +234,11 @@
        BUG_ON(buf_offs + buf->len > SL811_BUF_SIZE);
        BUG_ON(buf->len > (SL811_BUF_SIZE / FLIP_BUFFERS));
 
-       if (buf->hc & SL11H_HCTLMASK_WRITE && buf->len > 0) {
+       if ((buf->hc & SL11H_HCTLMASK_WRITE) && (buf->len > 0)) {
                // transfer data from TD buffer to SL811 buffer memory
-               BUG_ON(buf->buf_addr == NULL);
+               BUG_ON(buf->dma_addr == 0);
                ohci_vdbg(hcd_to_ohci(hcd), "%s: Transferring %d of %d byte from %08x 
to %02x\n",
-                         __FUNCTION__, buf->len, buf->buf_len, (u32)buf->buf_addr,
+                         __FUNCTION__, buf->len, buf->buf_len, buf->dma_addr,
                          SL11H_DATA_START + buf_offs);
                sl811_dma_send_data(dev, buf, SL11H_DATA_START + buf_offs);
        }
@@ -241,15 +282,8 @@
 
        if (dev->current_td == NULL) {
                dev->current_td = td;
-
-               if (td->hwCBP != 0) {
-                       dev->buf_addr = (void*)dma_to_virt(hcd->self.controller,
-                                                          get_hw_fld(td, CBP));
-                       dev->buf_len = TD_BUF_LEN(td);
-               } else {
-                       dev->buf_addr = NULL;
-                       dev->buf_len = 0;
-               }
+               dev->dma_addr = get_hw_fld(td, CBP);
+               dev->buf_len = TD_BUF_LEN(td);
        }
 
        pid = ed_td_to_pid[ed_pid(ed_flags)][td_pid(td_flags)];
@@ -286,7 +320,7 @@
                len = dev->buf_len;
        }
 
-       buf->buf_addr = dev->buf_addr;
+       buf->dma_addr = dev->dma_addr;
        buf->buf_len = dev->buf_len;
 
        buf->hc = hc_flags;
@@ -297,11 +331,11 @@
 
        if (start_xfer(hcd, dev, flip)) {
                if (dev->buf_len > len) {
-                       dev->buf_addr += len;
+                       dev->dma_addr = update_cbp(dev->dma_addr, get_hw_fld(td, BE), 
len);
                        dev->buf_len -= len;
                } else {
                        dev->buf_len = 0;
-                       dev->buf_addr = NULL;
+                       dev->dma_addr = 0;
                }
        }
 
@@ -365,16 +399,23 @@
                        td = find_td(ohci, dev, ed);
                }
 
-               if ((td && (ed_flags & ED_LOWSPEED) && (rem < HcLsThreshold)) ||
-                   ((td == dev->current_td) && (dev->buf_len == 0))) {
-                       td = NULL;
-                       ret = 1;
+               if (td == NULL) {
+                       continue;
+               }
+               if (ed_flags & ED_ISO) {
+                       // operation not supported, fail with -EIO
+                       printk("%s: ISO transfers not supported\n", __FUNCTION__);
+                       retire_td(hcd, td, ed, 0x0a);
+                       continue;
                }
 
-               if (td != NULL) {
-                       done = process_td(ohci, td, flip);
-                       ret = done;
+               if (((ed_flags & ED_LOWSPEED) && (rem < HcLsThreshold)) ||
+                   ((td == dev->current_td) && (dev->buf_len == 0))) {
+                       ret = 1;
+                       continue;
                }
+               done = process_td(ohci, td, flip);
+               ret |= done;
        }
 
        return ret;
@@ -407,10 +448,12 @@
        }
        // process ctrl EDs until cbsr limit reached
        if ((HcControl & OHCI_CTRL_CLE) && (dev->cbc <= cbsr)) {
+#ifdef MULT_CTRL
                if ((HcControlCurrentED == 0) && (HcCmdStatus & OHCI_CLF)) {
                        HcControlCurrentED = HcControlHeadED;
                        HcCmdStatus &= ~OHCI_CLF;
                }
+#endif
                if (HcControlCurrentED != 0) {
                        ret = process_ed_list(ohci, &HcControlCurrentED, flip);
                        if (ret > 0) {
@@ -494,9 +537,8 @@
        return ret;
 }
 
-static u32 retire_td(struct usb_hcd *hcd, struct td *td, struct ed *ed, u32 cc)
+static void retire_td(struct usb_hcd *hcd, struct td *td, struct ed *ed, u32 cc)
 {
-       u32 ohci_int_status = 0;
        struct hc_sl811_dev *dev = hcd_to_sl811_dev(hcd);
        struct ohci_hcd *ohci = hcd_to_ohci(hcd);
        struct ohci_regs *regs = ohci->regs;
@@ -506,13 +548,14 @@
        u32 int_delay = (cc == TD_CC_NOERROR) ? (td_flags & TD_DI) >> 21 : 0;
        u32 ed_halt = 0;
 
-       BUG_ON(TD_CC_GET(td_flags) != TD_NOTACCESSED);
+       WARN_ON(TD_CC_GET(td_flags) != TD_NOTACCESSED);
 
        if (dev->current_td == td) {
                dev->current_td = NULL;
        }
 
-       ohci_dbg(ohci, "%s: Retiring TD %08x of ED %08x\n", __FUNCTION__, (u32)td, 
(u32)ed);
+       ohci_vdbg(ohci, "%s: Retiring TD %08x of ED %08x with CC=%d\n", __FUNCTION__, 
(u32)td,
+                 (u32)ed, cc);
        if (dev->num_bufs > 1) {
                WARN_ON(1);
                kill_xfer_bufs(hcd, dev, td);
@@ -522,7 +565,7 @@
        if (!(ed_flags & ED_ISO)) {
                ed_halt = (cc != TD_CC_NOERROR) ? cpu_to_le32(ED_H) : 0;
                if (ed_halt) {
-                       ohci_dbg(ohci, "%s: ED %08x (TD %08x) Halted due to error: 
%d\n",
+                       ohci_vdbg(ohci, "%s: ED %08x (TD %08x) Halted due to error: 
%d\n",
                                 __FUNCTION__, (u32)ed, (u32)td, cc);
                }
                ed_halt |= ((td_flags & TD_T) == TD_T_DATA1) ? cpu_to_le32(ED_C) : 0;
@@ -530,13 +573,11 @@
        ed->hwHeadP = td->hwNextTD | ed_halt;
 
        td->hwNextTD = HcDoneHead;
-       HcDoneHead = td_dma;
+       HcDoneHead = cpu_to_le32(td_dma);
 
        if ((int_delay != 7) && (int_delay < dev->intrdelay)) {
                dev->intrdelay = int_delay;
        }
-
-       return ohci_int_status;
 }
 
 static void update_data_toggle(struct usb_hcd *hcd, struct td *td)
@@ -579,40 +620,11 @@
        return ret;
 }
 
-static int update_cbp(struct td *td, int len)
-{
-       u32 cbp = get_hw_fld(td, CBP);
-       u32 be = get_hw_fld(td, BE);
-       int finished = 0;
-
-       if (cbp == 0) {
-               return 1;
-       }
-
-       if (TD_BUF_LEN(td) == len) {
-               cbp = 0;
-               finished = 1;
-       } else {
-               u32 chunk_size = DMA_XFER_SIZE(cbp, len);
-
-               if (chunk_size == len) {
-                       cbp += len;
-               } else {
-                       cbp = (be & ~PAGE_MASK) | (len - chunk_size);
-               }
-               WARN_ON(cbp > be);
-       }
-       set_hw_fld(td, CBP, cbp);
-
-       return finished;
-}
-
 #define TD_EC_GET(info) (((info) & TD_EC) >> 26)
 #define TD_EC_SET_HW(td, ec) set_hwinfo(td, (get_hwinfo(td) & ~TD_EC) | (((ec) << 26) 
& TD_EC))
 
-static u32 update_td_status(struct usb_hcd *hcd, struct xfer_buf *buf, struct td *td)
+static void update_td_status(struct usb_hcd *hcd, struct xfer_buf *buf, struct td *td)
 {
-       u32 ohci_int_status = 0;
        struct ed *ed = td->ed;
        struct hc_sl811_dev *dev = hcd_to_sl811_dev(hcd);
        u32 td_flags = get_hwinfo(td);
@@ -623,8 +635,6 @@
        int td_halt = 0;
        u32 cc = TD_CC_NOERROR;
 
-       BUG_ON(iso);
-
        WARN_ON(TD_CC_GET(td_flags) != TD_NOTACCESSED);
 
        if (unlikely((pkt_stat & SL811_PKT_ERR_MASK) != 0)) {
@@ -635,11 +645,11 @@
                        if (dev->num_bufs > 1) {
                                kill_xfer_bufs(hcd, dev, td);
                        }
-                       return 0;
+                       return;
                }
                td_halt = 1;
                if (pkt_stat & SL11H_STATMASK_STALL) {
-                       ohci_dbg(hcd_to_ohci(hcd), "%s: Got STALL on TD %08x of ED 
%08x\n",
+                       ohci_vdbg(hcd_to_ohci(hcd), "%s: Got STALL on TD %08x of ED 
%08x\n",
                                 __FUNCTION__, (u32)td, (u32)ed);
                        cc = TD_CC_STALL;
                } else if (pkt_stat & (SL11H_STATMASK_TMOUT |
@@ -647,8 +657,6 @@
                                       SL11H_STATMASK_SEQ)) {
                        int err_count = TD_EC_GET(td_flags) + 1;
 
-                       ohci_dbg(hcd_to_ohci(hcd), "%s: XMIT ERROR on TD %08x of ED 
%08x\n", __FUNCTION__,
-                                 (u32)td, (u32)ed);
                        if (pkt_stat & SL11H_STATMASK_TMOUT) {
                                cc = TD_DEVNOTRESP;
                        } else if (pkt_stat & SL11H_STATMASK_SEQ) {
@@ -664,46 +672,36 @@
                                if (dev->num_bufs > 1) {
                                        kill_xfer_bufs(hcd, dev, td);
                                }
-                               return 0;
+                               return;
                        }
+                       ohci_dbg(hcd_to_ohci(hcd), "%s: XMIT ERROR %d on TD %08x of ED 
%08x\n",
+                                __FUNCTION__, cc, (u32)td, (u32)ed);
                } else if (pkt_stat & SL11H_STATMASK_OVF) {
                        cc = TD_DATAOVERRUN;
+                       ohci_warn(hcd_to_ohci(hcd), "%s: Data overrun: pkt_stat: 
%02x\n",
+                                 __FUNCTION__, pkt_stat);
+                                 
                }
        } else if (pkt_stat & SL11H_STATMASK_ACK) {
-               ohci_dbg(hcd_to_ohci(hcd), "%s: Got ACK on TD %08x of ED %08x\n", 
__FUNCTION__,
-                         (u32)td, (u32)ed);
+               u32 cbp = get_hw_fld(td, CBP);
 
-               if (buf->count > TD_BUF_LEN(td)) {
-                       ohci_warn(hcd_to_ohci(hcd),
-                                 "%s: Data overrun: bufsize: %04x datasize: %04x\n", 
__FUNCTION__,
-                                 TD_BUF_LEN(td), buf->count);
-                       cc = TD_DATAOVERRUN;
-                       goto err;
-               }
+               ohci_vdbg(hcd_to_ohci(hcd), "%s: Got ACK on TD %08x of ED %08x\n", 
__FUNCTION__,
+                         (u32)td, (u32)ed);
 
                TD_EC_SET_HW(td, 0);
 
-               td_finished = update_cbp(td, buf->count);
-
+               cbp = update_cbp(cbp, get_hw_fld(td, BE), buf->count);
+               set_hw_fld(td, CBP, cbp);
+               td_finished = cbp == 0;
                if (!td_finished && (buf->count < ed_mps(ed_flags))) {
-                       u32 cbp = get_hw_fld(td, CBP);
-                       u32 be = get_hw_fld(td, BE);
-
-                       if (!(td_flags & TD_R) || (buf->count == 0)) {
+                       if (!(td_flags & TD_R)) {
                                td_halt = 1;
                                ohci_warn(hcd_to_ohci(hcd),
                                          "%s: Data underrun: %d byte transferred, %d 
byte requested\n",
-                                        __FUNCTION__, buf->count, ed_mps(ed_flags));
+                                         __FUNCTION__, buf->count, ed_mps(ed_flags));
                                cc = TD_DATAUNDERRUN;
                                goto err;
                        }
-                       if ((be & PAGE_MASK) == ((cbp + buf->count - 1) & PAGE_MASK)) {
-                               be = cbp + buf->count - 1;
-                       } else {
-                               be = (be & ~PAGE_MASK) + ((cbp + buf->count - 1) & 
~PAGE_MASK);
-                       }
-                       set_hw_fld(td, BE, be);
-                       set_hw_fld(td, CBP, 0);
                        td_finished = 1;
                }
        } else {
@@ -712,11 +710,9 @@
        }
 
        if (pkt_stat & SL11H_STATMASK_ACK) {
-               if (buf->buf_len > FLIP_BUFFERS * buf->count) {
-                       buf->buf_len -= FLIP_BUFFERS * buf->count;
-                       buf->buf_addr += FLIP_BUFFERS * buf->count;
+               if (buf->buf_len > buf->count) {
+                       buf->buf_len -= buf->count;
                } else {
-                       buf->buf_addr = NULL;
                        buf->buf_len = 0;
                }
                if (buf->len > buf->buf_len) {
@@ -730,30 +726,24 @@
 
  err:
        if (td_finished || (td_halt && !iso)) {
-               ohci_int_status |= retire_td(hcd, td, ed, cc);
+               retire_td(hcd, td, ed, cc);
        }
-
-       return ohci_int_status;
 }
 
-static u32 kill_current_td(struct usb_hcd *hcd, struct hc_sl811_dev *dev)
+static void kill_current_td(struct usb_hcd *hcd, struct hc_sl811_dev *dev)
 {
        struct td *td = dev->current_td;
-       u32 ohci_int_status = 0;
 
        BUG_ON(td == NULL);
        kill_xfer_bufs(hcd, dev, td);
 
        ohci_warn(hcd_to_ohci(hcd), "%s: killing TD %08x (ED: %08x)\n",
                  __FUNCTION__, (u32)td, (u32)td->ed);
-       ohci_int_status |= retire_td(hcd, td, td->ed, TD_DEVNOTRESP);
-
-       return ohci_int_status;
+       retire_td(hcd, td, td->ed, TD_DEVNOTRESP);
 }
 
-static u32 finish_xfer(struct usb_hcd *hcd, struct hc_sl811_dev *dev, int flip)
+static void finish_xfer(struct usb_hcd *hcd, struct hc_sl811_dev *dev, int flip)
 {
-       u32 ohci_int_status = 0;
        struct xfer_buf *buf = &dev->xfer_buf[flip];
        struct td *td = buf->td;
        int reg_offs = flip * 8;
@@ -764,6 +754,13 @@
                __hc_sl811_read_regs(dev, SL11H_PKTSTATREG + reg_offs, &buf->rcv_data,
                                     sizeof(buf->rcv_data));
                buf->count = buf->len - buf->count;
+               if (buf->count > TD_BUF_LEN(td)) {
+                       ohci_warn(hcd_to_ohci(hcd),
+                                 "%s: Data overrun: bufsize: %04x datasize: %04x\n", 
__FUNCTION__,
+                                 TD_BUF_LEN(td), buf->count);
+                       retire_td(hcd, td, td->ed, TD_DATAOVERRUN);
+                       return;
+               }
                if (!(buf->hc & SL11H_HCTLMASK_WRITE)) {
                        if (check_data_toggle(td, buf, hcd)) {
                                buf->pkt_stat &= ~SL11H_STATMASK_SEQ;
@@ -781,24 +778,20 @@
                                if (buf->count > 0) {
                                        ohci_vdbg(hcd_to_ohci(hcd),
                                                  "%s: Transferring %d of %d byte from 
%02x to %08x\n",
-                                                 __FUNCTION__, buf->count, 
buf->buf_len, offset,
-                                                 (u32)buf->buf_addr);
-                                       BUG_ON(TD_BUF_LEN(td) == 0);
+                                                 __FUNCTION__, buf->count, 
buf->buf_len, offset, buf->dma_addr);
                                        sl811_dma_recv_data(dev, buf, SL11H_DATA_START 
+ buf_offs);
                                }
                        }
                } else {
                        buf->pkt_stat &= ~SL11H_STATMASK_SEQ;
                }
-               ohci_int_status = update_td_status(hcd, buf, td);
+               update_td_status(hcd, buf, td);
        }
 
        dev->num_bufs--;
        BUG_ON(dev->num_bufs > FLIP_BUFFERS);
        dev->buf_map &= ~(1 << flip);
        buf->td = NULL;
-
-       return ohci_int_status;
 }
 
 /*
@@ -855,7 +848,7 @@
                u8 svc_mask;
 
                int_status = __hc_sl811_read_reg(dev, SL11H_INTSTATREG);
-               BUG_ON((FLIP_BUFFERS == 1) && (int_status & SL11H_INTMASK_XFERDONE_B));
+               WARN_ON((FLIP_BUFFERS == 1) && (int_status & 
SL11H_INTMASK_XFERDONE_B));
                svc_mask = int_status & int_mask;
                if (handled && (svc_mask == 0)) {
                        break;
@@ -877,6 +870,7 @@
                handled = 0x80000000;
                __hc_sl811_write_reg(dev, SL11H_INTSTATREG,
                                     svc_mask & 
~(SL11H_INTMASK_RESUME|SL11H_INTMASK_INSRMV));
+
                if (svc_mask & SL11H_INTMASK_INSRMV) {
                        svc_mask &= ~SL11H_INTMASK_INSRMV;
                        int_mask &= ~SL11H_INTMASK_INSRMV;
@@ -886,7 +880,7 @@
 
                        dev->dev_state &= ~(DEV_ACTIVE | DEV_SOF);
                        if (dev->current_td) {
-                               ohci_int_status |= kill_current_td(hcd, dev);
+                               kill_current_td(hcd, dev);
                                ohci_int_status |= OHCI_INTR_SF;
                        }
 
@@ -967,7 +961,7 @@
                                int soc = (HcCmdStatus - OHCI_SOC) & OHCI_SOC;
 
                                if (dev->current_td) {
-                                       ohci_int_status |= kill_current_td(hcd, dev);
+                                       kill_current_td(hcd, dev);
                                }
 
                                ohci_warn(ohci, "%s: Scheduling overrun at frame 
%04x\n",
@@ -1040,7 +1034,7 @@
                                        svc_mask &= ~im;
                                        handled |= im;
 
-                                       ohci_int_status |= finish_xfer(hcd, dev, flip);
+                                       finish_xfer(hcd, dev, flip);
                                        if (dev->dev_state & DEV_SOF) {
                                                if (dev->current_td && dev->buf_len > 
0) {
                                                        process_td(ohci, 
dev->current_td, flip);
@@ -1070,8 +1064,8 @@
        if (ohci_int_status != 0) {
                HcIntrStatus |= ohci_int_status;
                if ((HcIntrEnable & OHCI_INTR_MIE) && (ohci_int_status & 
HcIntrEnable)) {
-                       ohci_dbg(ohci, "%s: Calling OHCI interrupt handler: 
%08x(%08x):%08x\n",
-                                __FUNCTION__, HcIntrStatus, ohci_int_status, 
HcIntrEnable);
+                       ohci_vdbg(ohci, "%s: Calling OHCI interrupt handler: 
%08x(%08x):%08x\n",
+                                 __FUNCTION__, HcIntrStatus, ohci_int_status, 
HcIntrEnable);
                        // call the OHCI IRQ handler
                        if (usb_hcd_irq(hcd->irq, hcd, pt_regs) != IRQ_HANDLED) {
                                ohci_warn(ohci, "%s: Spurious OHCI Interrupt: 
%08x(%08x):%08x\n",
--- linux-2.6.8.1/drivers/usb/host/ohci-sl811.c 2004-09-13 18:56:15.000000000 +0200
+++ linux-2.6.8.1-karo/drivers/usb/host/ohci-sl811.c    2004-09-13 19:09:24.000000000 
+0200
@@ -442,6 +442,15 @@
        local_irq_restore(flags);
 }
 
+static void usb_hcd_sl811_release(struct usb_bus *bus)
+{
+       struct usb_hcd *hcd = bus->hcpriv;
+
+       if (hcd != NULL) {
+               hcd->driver->hcd_free(hcd);
+       }
+}
+
 /**
  * usb_hcd_sl811_probe - initialize HC-SL811-based HCDs
  * Context: !in_interrupt()
@@ -452,8 +461,7 @@
  *
  * Store this function in the HCD's struct pci_driver as probe().
  */
-static int usb_hcd_sl811_probe(struct hc_driver *driver, struct usb_hcd **hcd_out,
-                              struct hc_sl811_dev *dev)
+static int usb_hcd_sl811_probe(struct hc_driver *driver, struct hc_sl811_dev *dev)
 {
        int retval;
        struct usb_hcd *hcd = NULL;
@@ -515,6 +523,8 @@
        usb_bus_init(&hcd->self);
        hcd->self.op = &usb_hcd_operations;
        hcd->self.hcpriv = hcd;
+       hcd->self.release = usb_hcd_sl811_release;
+       init_timer(&hcd->rh_timer);
 
        INIT_LIST_HEAD(&hcd->dev_list);
 
@@ -530,8 +540,6 @@
        info("%s (HC-%s) at 0x%p, irq %d\n", hcd->description,
             chip_names[dev->hw_rev & 0x0f], hcd->regs, hcd->irq);
 
-       *hcd_out = hcd;
-
        return 0;
 
  err3:
@@ -587,8 +595,6 @@
 
        usb_deregister_bus(&hcd->self);
 
-       hcd->driver->hcd_free(hcd);
-
        return 0;
 }
 
@@ -802,7 +808,7 @@
                goto out;
        }
 
-       ret = usb_hcd_sl811_probe(&ohci_sl811_hc_driver, &hcd, dev);
+       ret = usb_hcd_sl811_probe(&ohci_sl811_hc_driver, dev);
        if (ret == 0) {
                return ret;
        }
@@ -851,47 +857,6 @@
        return 0;
 }
 
-static void __sl811_release(struct device *dev)
-{
-       struct hc_sl811_dev *sl811_dev = dev_get_drvdata(dev);
-
-       printk("%s: dev=%08x\n", __FUNCTION__, (u32)dev);
-       if (sl811_dev != NULL) {
-               kfree(sl811_dev);
-       }
-}
-
-#define MALLOC_SIZE sizeof(struct hc_sl811_dev)
-static int __sl811_probe(struct device *dev, struct resource *mem, struct resource 
*irq)
-{
-       int ret;
-       struct hc_sl811_dev *sl811_dev;
-
-       sl811_dev = kmalloc(MALLOC_SIZE, GFP_KERNEL);
-       if (sl811_dev == NULL) {
-               return -ENOMEM;
-       }
-       memset(sl811_dev, 0, MALLOC_SIZE);
-
-       sl811_dev->irq = NO_IRQ;
-
-       sl811_dev->dev.parent = dev;
-       sl811_dev->dev.bus = &platform_bus_type;
-       sl811_dev->dev.release = __sl811_release;
-
-       //spin_lock_init(&sl811_dev->irq_lock);
-
-       dev_set_drvdata(dev, sl811_dev);
-
-       ret = ohci_hcd_sl811_drv_probe(sl811_dev);
-
-       if (ret != 0) {
-               dev_set_drvdata(dev, NULL);
-       }
-
-       return ret;
-}
-
 static int usb_hcd_sl811_suspend(struct hc_sl811_dev *dev, u32 state)
 {
        struct usb_hcd          *hcd;
@@ -975,31 +940,41 @@
        return retval;
 }
 
-static struct hc_sl811_driver ohci_hcd_sl811_driver = {
-       .drv = {
-               .name   = "sl811-ohci",
-               .bus    = &platform_bus_type,
-       },
-       .devid  = 0,
-       .probe  = ohci_hcd_sl811_drv_probe,
-       .remove = ohci_hcd_sl811_drv_remove,
-#ifdef CONFIG_PM
-       .suspend = usb_hcd_sl811_suspend,
-       .resume = usb_hcd_sl811_resume,
-#endif
-};
+static void sl811_bus_release(struct device *dev)
+{
+       struct hc_sl811_dev *sl811_dev = dev_get_drvdata(dev);
+
+       printk("%s: dev=%08x\n", __FUNCTION__, (u32)dev);
+       if (sl811_dev != NULL) {
+               kfree(sl811_dev);
+       }
+}
 
 static int sl811_bus_probe(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct resource *mem, *irq = NULL;
-       int ret = -ENODEV;
-
-       mem = &pdev->resource[0];
-       if (pdev->num_resources == 2) {
-               irq = &pdev->resource[1];
+       int ret = 0;
+       struct hc_sl811_dev *sl811_dev;
+       struct hc_sl811_driver *drv = SL811_DRV(dev->driver);
+
+       sl811_dev = kmalloc(sizeof(struct hc_sl811_dev), GFP_KERNEL);
+       if (sl811_dev == NULL) {
+               return -ENOMEM;
+       }
+       memset(sl811_dev, 0, sizeof(struct hc_sl811_dev));
+
+       sl811_dev->irq = NO_IRQ;
+
+       sl811_dev->dev.parent = dev;
+       sl811_dev->dev.bus = &platform_bus_type;
+       sl811_dev->dev.release = sl811_bus_release;
+
+       dev_set_drvdata(dev, sl811_dev);
+       if (drv->probe) {
+               ret = drv->probe(sl811_dev);
+               if (ret != 0) {
+                       dev_set_drvdata(dev, NULL);
+               }
        }
-       ret = __sl811_probe(dev, mem, irq);
 
        return ret;
 }
@@ -1041,15 +1016,29 @@
        return ret;
 }
 
+static struct hc_sl811_driver ohci_hcd_sl811_driver = {
+       .drv = {
+               .name   = "sl811-ohci",
+               .bus    = &platform_bus_type,
+               .probe = sl811_bus_probe,
+               .remove = sl811_bus_remove,
+               .suspend = sl811_bus_suspend,
+               .resume = sl811_bus_resume,
+       },
+       .devid  = 0,
+       .probe  = ohci_hcd_sl811_drv_probe,
+       .remove = ohci_hcd_sl811_drv_remove,
+#ifdef CONFIG_PM
+       .suspend = usb_hcd_sl811_suspend,
+       .resume = usb_hcd_sl811_resume,
+#endif
+};
+
 static int hc_sl811_driver_register(struct hc_sl811_driver *driver)
 {
        int ret;
 
-       WARN_ON(driver->drv.suspend || driver->drv.resume || driver->drv.probe || 
driver->drv.remove);
-       driver->drv.probe = sl811_bus_probe;
-       driver->drv.remove = sl811_bus_remove;
-       driver->drv.suspend = sl811_bus_suspend;
-       driver->drv.resume = sl811_bus_resume;
+       WARN_ON(!driver->drv.suspend || !driver->drv.resume || !driver->drv.probe || 
!driver->drv.remove);
 
        ret = driver_register(&driver->drv);
 
--- linux-2.6.8.1/drivers/usb/host/ohci-sl811.h 2004-09-13 18:56:15.000000000 +0200
+++ linux-2.6.8.1-karo/drivers/usb/host/ohci-sl811.h    2004-09-13 19:09:24.000000000 
+0200
@@ -14,7 +14,9 @@
  *
  */
 
+#ifdef CONFIG_ARCH_KARO
 #include <asm/arch/karo.h>
+#endif
 
 //#define USE_DMA //Can't use DMA because of SL811 register address alignment :(
 #define FLIP_BUFFERS   1
@@ -134,7 +136,7 @@
 #define DEV_TRIGGERED  (DEV_CONN_CHK | DEV_OHCI_IRQ)
 
 struct xfer_buf {
-       void            *buf_addr;
+       dma_addr_t      dma_addr;
        int             buf_len;
        struct td       *td;
        union {
@@ -165,7 +167,8 @@
        struct tasklet_struct usb_reset_bh;
        struct xfer_buf xfer_buf[FLIP_BUFFERS];
        unsigned int    flip;
-       void            *buf_addr;
+       dma_addr_t      dma_addr;
+       //void          *buf_addr;
        int             buf_len;
        unsigned int    num_bufs;
        unsigned int    buf_map;
@@ -347,5 +350,5 @@
 static void hc_sl811_usb_reset(struct usb_hcd *hcd, int assert);
 static void hc_sl811_start_sof(struct usb_hcd *hcd, int lowspeed);
 static void ohci_sl811_bh(unsigned long data);
-static u32 retire_td(struct usb_hcd *hcd, struct td *td, struct ed *ed, u32 cc);
-static u32 kill_current_td(struct usb_hcd *hcd, struct hc_sl811_dev *dev);
+static void retire_td(struct usb_hcd *hcd, struct td *td, struct ed *ed, u32 cc);
+static void kill_current_td(struct usb_hcd *hcd, struct hc_sl811_dev *dev);

Reply via email to