[USB] Kind of works..
[people/balajirrao/gpxe.git] / src / drivers / bus / usb / ohci_hcd.c
index 0d542b7..52369c2 100644 (file)
@@ -24,7 +24,6 @@ static void ohci_usb_reset (struct ohci_hcd *ohci)
 
 static int ohci_init(struct ohci_hcd *ohci)
 {
-       mdelay(5000);   
        if (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
                u32 temp;
 
@@ -198,7 +197,6 @@ static inline int reset_port (struct ohci_hcd *ohci, unsigned port)
         * still being set when this returns.
         */
        mdelay(1);
-       dbg_port(ohci, "PORT ", port, roothub_portstatus(ohci, port));
        return 0;
 }
 
@@ -232,7 +230,7 @@ static struct ohci_td * ohci_alloc_td (struct ohci_hcd *hc, struct ohci_ed *ed)
 static inline void ohci_fill_td (struct ohci_hcd *ohci, struct ohci_td *td,
                                uint32_t info, unsigned long data, unsigned int len)
 {
-       info |= TD_DI_SET(7);
+       info |= TD_DI_SET(6);
 
        td->hwINFO = cpu_to_hc32(ohci, info);
        td->hwCBP = cpu_to_hc32(ohci, data);
@@ -307,10 +305,10 @@ static void ohci_add_urbp_to_ed(struct ohci_urb_priv *urbp, struct ohci_ed *ed)
        list_add_tail(&urbp->list, &ed->urbp_list);
 }
 
-//static void ohci_del_urbp_from_ed(struct ohci_urb_priv *urbp)
-//{
-//     list_del(&urbp->list);
-//}
+static void ohci_del_urbp_from_ed(struct ohci_urb_priv *urbp)
+{
+       list_del(&urbp->list);
+}
 
 static void ohci_add_td_to_urbp(struct ohci_td *td, struct ohci_urb_priv *urbp)
 {
@@ -360,12 +358,14 @@ static int ohci_submit_bulk(struct urb *urb, struct ohci_ed *ed)
                }
 
                ohci_fill_td(ohci, td, info, data, pktsze);
+               ohci_add_td_to_urbp(td, urbp);
                plink = &td->hwNextTD;
 
                data += pktsze;
                len -= pktsze;
        } while (len > 0);
 
+       urbp->last_td = td;
        /*
         * Build the new dummy TD and activate the old one
         */
@@ -374,15 +374,11 @@ static int ohci_submit_bulk(struct urb *urb, struct ohci_ed *ed)
                goto err_dummytd_malloc;
 
        *plink = cpu_to_hc32(ohci, td->dma);
-
-       wmb();
-
        ed->dummy_td = td;
        ed->hwTailP = cpu_to_hc32(ohci, td->dma);
-       writel(OHCI_BLF, &ohci->regs->cmdstatus); 
-
        wmb();
-       
+
+       writel(OHCI_BLF, &ohci->regs->cmdstatus); 
        return 0;
 
        ohci_free_td(ed->dummy_td);
@@ -436,6 +432,7 @@ static int ohci_submit_control(struct urb *urb, struct ohci_ed *ed)
                info = TD_CC | TD_R | TD_T_DATA1;
                info |= is_out ? TD_DP_OUT : TD_DP_IN;
                ohci_fill_td(ohci, td, info, data, pktsze);
+               ohci_add_td_to_urbp(td, urbp);
                plink = &td->hwNextTD;
 
 //             data += pktsze;
@@ -521,6 +518,7 @@ static int ohci_enqueue_urb(struct usb_hcd *hcd, struct urb *urb)
                                writel(cpu_to_hc32(ohci, ed->dma), &ohci->regs->ed_controlhead);
                                ohci->hc_control |= OHCI_CTRL_CLE;
                                writel(ohci->hc_control, &ohci->regs->control);
+                               wmb();
                        } else {
                                ohci->last_control_ed->hwNextED = cpu_to_hc32(ohci, ed->dma);
                        }
@@ -528,17 +526,16 @@ static int ohci_enqueue_urb(struct usb_hcd *hcd, struct urb *urb)
                } else {
                        /* Check to see if this is the first ed */
                        if (!readl(&ohci->regs->ed_bulkhead)) {
+                               writel(0, &ohci->regs->ed_bulkcurrent);
                                writel(cpu_to_hc32(ohci, ed->dma), &ohci->regs->ed_bulkhead);
                                ohci->hc_control |= OHCI_CTRL_BLE;
                                writel(ohci->hc_control, &ohci->regs->control);
-                               writel(0, &ohci->regs->ed_bulkcurrent);
+                               wmb();
                        } else {
                                ohci->last_bulk_ed->hwNextED = cpu_to_hc32(ohci, ed->dma);
                        }
                        ohci->last_bulk_ed = ed;
                }
-
-                               writel(ohci->hc_control, &ohci->regs->control);
        }
        
        /* Update the ed's fa */
@@ -547,6 +544,7 @@ static int ohci_enqueue_urb(struct usb_hcd *hcd, struct urb *urb)
        info &= ~((1 << 7) - 1);
        info |= (urb->udev->devnum);
        ed->hwINFO = cpu_to_hc32(ohci, info);
+       wmb();
 
        /* Add the urbp to the ED's list */
        ohci_add_urbp_to_ed(urbp, ed);
@@ -569,8 +567,22 @@ err_hcpriv_malloc:
 err_urb_malloc:
        return ret;
 }
-static void ohci_unlink_urb(struct urb *urb __unused)
+static void ohci_unlink_urb(struct urb *urb)
 {
+       struct ohci_td *td;
+       struct ohci_urb_priv *urbp;
+       struct ohci_hcd *ohci;
+
+       ohci = hcd_to_ohci(urb->udev->hcd);
+       urbp = urb->hcpriv;
+       list_for_each_entry(td, &urbp->td_list, list) {
+               list_del(&td->list);
+               mdelay(2);
+               ohci_free_td(td);
+       }
+       ohci_del_urbp_from_ed(urbp);
+       free(urbp);
+
 }
 
 static int ohci_urb_status(struct urb *urb)
@@ -581,10 +593,12 @@ static int ohci_urb_status(struct urb *urb)
        struct list_head *p;
        struct ohci_hcd *ohci = hcd_to_ohci(urb->udev->hcd);
        uint32_t info;
+       uint32_t be, cbp;
 
        /* Check for the status of the first td *///
        info = hc32_to_cpu(ohci, urbp->first_td->hwINFO);
-
+//             DBG("%lx  %p %lx\n", urbp->first_td->hwINFO, urb, TD_CC_GET(info));
+//                     mdelay(1000);                   
        if (TD_CC_GET(info) != 0) {
                if (TD_CC_GET(info) == 0xf) {
                        ret = USB_URB_STATUS_INPROGRESS;
@@ -599,9 +613,8 @@ static int ohci_urb_status(struct urb *urb)
        /* Optimie by looking at last_td directly. */
        td = urbp->last_td;
        info = hc32_to_cpu(ohci, urbp->last_td->hwINFO);
-       
+//     DBG("last td = %lx %lx\n", TD_CC_GET(info), urbp->last_td->hwINFO);     
        if (TD_CC_GET(info) == 0) {
-               unsigned long be, cbp;
                be = hc32_to_cpu(ohci, td->hwBE);
                cbp = hc32_to_cpu(ohci, td->hwCBP);
                if (cbp == 0) {
@@ -730,8 +743,8 @@ static int ohci_hcd_pci_probe(struct pci_device *pci,
        if (pci->class != PCI_CLASS_SERIAL_USB_OHCI)
                return -ENOTTY;
 
-//     if (once == 1)
-//             return -1;
+       if (once == 1)
+               return -1;
 
        once = 1;
 
@@ -768,7 +781,6 @@ static int ohci_hcd_pci_probe(struct pci_device *pci,
        /* Look for devices at ports */
 mdelay(100);   
        for (port = 0; port < ohci->num_ports; port++) {
-                               dbg_port(ohci, "PORT", port, roothub_portstatus(ohci,  port));
                uint32_t status = roothub_portstatus (ohci, port);
                if (!(status & RH_PS_CCS)) {
                        DBG("No device on port %d\n", port + 1);