diff options
Diffstat (limited to 'cpu/ppc4xx/usb_ohci.c')
-rw-r--r-- | cpu/ppc4xx/usb_ohci.c | 1218 |
1 files changed, 606 insertions, 612 deletions
diff --git a/cpu/ppc4xx/usb_ohci.c b/cpu/ppc4xx/usb_ohci.c index 6176709..d53909e 100644 --- a/cpu/ppc4xx/usb_ohci.c +++ b/cpu/ppc4xx/usb_ohci.c @@ -1,5 +1,5 @@ /* - * URB OHCI HCD (Host Controller Driver) for USB on the PPC 440. + * URB OHCI HCD (Host Controller Driver) for USB on the PPC440EP. * * (C) Copyright 2003-2004 * Gary Jennejohn, DENX Software Engineering <gj@denx.de> @@ -43,6 +43,7 @@ #include <malloc.h> #include <usb.h> #include "usb_ohci.h" + #include "usbdev.h" #define OHCI_USE_NPS /* force NoPowerSwitching mode */ @@ -64,7 +65,7 @@ #define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg) #else #define dbg(format, arg...) do {} while(0) -#endif /* DEBUG */ +#endif /* DEBUG */ #define err(format, arg...) printf("ERROR: " format "\n", ## arg) #ifdef SHOW_INFO #define info(format, arg...) printf("INFO: " format "\n", ## arg) @@ -75,7 +76,7 @@ #define m16_swap(x) swap_16(x) #define m32_swap(x) swap_32(x) -#if 1 +#ifdef CONFIG_440_EP #define ohci_cpu_to_le16(x) (x) #define ohci_cpu_to_le32(x) (x) #else @@ -97,6 +98,8 @@ urb_priv_t urb_priv; int got_rhsc; /* device which was disconnected */ struct usb_device *devgone; +/* flag guarding URB transation */ +int urb_finished = 0; /*-------------------------------------------------------------------------*/ @@ -112,29 +115,21 @@ struct usb_device *devgone; temp = readl (&hc->regs->roothub.register); \ temp; }) -static u32 roothub_a(struct ohci *hc) -{ - return read_roothub(hc, a, 0xfc0fe000); -} -static inline u32 roothub_b(struct ohci *hc) -{ - return readl(&hc->regs->roothub.b); -} -static inline u32 roothub_status(struct ohci *hc) -{ - return readl(&hc->regs->roothub.status); -} -static u32 roothub_portstatus(struct ohci *hc, int i) -{ - return read_roothub(hc, portstatus[i], 0xffe0fce0); -} +static u32 roothub_a (struct ohci *hc) + { return read_roothub (hc, a, 0xfc0fe000); } +static inline u32 roothub_b (struct ohci *hc) + { return readl (&hc->regs->roothub.b); } +static inline u32 roothub_status (struct ohci *hc) + { return readl (&hc->regs->roothub.status); } +static u32 roothub_portstatus (struct ohci *hc, int i) + { return read_roothub (hc, portstatus [i], 0xffe0fce0); } + /* forward declaration */ -static int hc_interrupt(void); +static int hc_interrupt (void); static void -td_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, urb_priv_t * urb, - int interval); +td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer, + int transfer_len, struct devrequest * setup, urb_priv_t * urb, int interval); /*-------------------------------------------------------------------------* * URB support functions @@ -142,11 +137,11 @@ td_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, /* free HCD-private data associated with this URB */ -static void urb_free_priv(urb_priv_t * urb) +static void urb_free_priv (urb_priv_t * urb) { - int i; - int last; - struct td *td; + int i; + int last; + struct td * td; last = urb->length - 1; if (last >= 0) { @@ -163,218 +158,228 @@ static void urb_free_priv(urb_priv_t * urb) /*-------------------------------------------------------------------------*/ #ifdef DEBUG -static int sohci_get_current_frame_number(struct usb_device *dev); +static int sohci_get_current_frame_number (struct usb_device * dev); /* debug| print the main components of an URB * small: 0) header + data packets 1) just header */ -static void pkt_print(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, char *str, - int small) +static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffer, + int transfer_len, struct devrequest * setup, char * str, int small) { - urb_priv_t *purb = &urb_priv; + urb_priv_t * purb = &urb_priv; dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx", - str, - sohci_get_current_frame_number(dev), - usb_pipedevice(pipe), - usb_pipeendpoint(pipe), - usb_pipeout(pipe) ? 'O' : 'I', - usb_pipetype(pipe) < 2 ? (usb_pipeint(pipe) ? "INTR" : "ISOC") : - (usb_pipecontrol(pipe) ? "CTRL" : "BULK"), - purb->actual_length, transfer_len, dev->status); + str, + sohci_get_current_frame_number (dev), + usb_pipedevice (pipe), + usb_pipeendpoint (pipe), + usb_pipeout (pipe)? 'O': 'I', + usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): + (usb_pipecontrol (pipe)? "CTRL": "BULK"), + purb->actual_length, + transfer_len, dev->status); #ifdef OHCI_VERBOSE_DEBUG if (!small) { int i, len; - if (usb_pipecontrol(pipe)) { - printf(__FILE__ ": cmd(8):"); - for (i = 0; i < 8; i++) - printf(" %02x", ((__u8 *) setup)[i]); - printf("\n"); + if (usb_pipecontrol (pipe)) { + printf (__FILE__ ": cmd(8):"); + for (i = 0; i < 8 ; i++) + printf (" %02x", ((__u8 *) setup) [i]); + printf ("\n"); } if (transfer_len > 0 && buffer) { - printf(__FILE__ ": data(%d/%d):", - purb->actual_length, transfer_len); - len = usb_pipeout(pipe) ? - transfer_len : purb->actual_length; + printf (__FILE__ ": data(%d/%d):", + purb->actual_length, + transfer_len); + len = usb_pipeout (pipe)? + transfer_len: purb->actual_length; for (i = 0; i < 16 && i < len; i++) - printf(" %02x", ((__u8 *) buffer)[i]); - printf("%s\n", i < len ? "..." : ""); + printf (" %02x", ((__u8 *) buffer) [i]); + printf ("%s\n", i < len? "...": ""); } } #endif } /* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/ -void ep_print_int_eds(ohci_t * ohci, char *str) -{ +void ep_print_int_eds (ohci_t *ohci, char * str) { int i, j; - __u32 *ed_p; - for (i = 0; i < 32; i++) { + __u32 * ed_p; + for (i= 0; i < 32; i++) { j = 5; - ed_p = &(ohci->hcca->int_table[i]); + ed_p = &(ohci->hcca->int_table [i]); if (*ed_p == 0) - continue; - printf(__FILE__ ": %s branch int %2d(%2x):", str, i, i); + continue; + printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i); while (*ed_p != 0 && j--) { - ed_t *ed = (ed_t *) ohci_cpu_to_le32(ed_p); - printf(" ed: %4x;", ed->hwINFO); + ed_t *ed = (ed_t *)ohci_cpu_to_le32(ed_p); + printf (" ed: %4x;", ed->hwINFO); ed_p = &ed->hwNextED; } - printf("\n"); + printf ("\n"); } } -static void ohci_dump_intr_mask(char *label, __u32 mask) +static void ohci_dump_intr_mask (char *label, __u32 mask) { - dbg("%s: 0x%08x%s%s%s%s%s%s%s%s%s", - label, - mask, - (mask & OHCI_INTR_MIE) ? " MIE" : "", - (mask & OHCI_INTR_OC) ? " OC" : "", - (mask & OHCI_INTR_RHSC) ? " RHSC" : "", - (mask & OHCI_INTR_FNO) ? " FNO" : "", - (mask & OHCI_INTR_UE) ? " UE" : "", - (mask & OHCI_INTR_RD) ? " RD" : "", - (mask & OHCI_INTR_SF) ? " SF" : "", - (mask & OHCI_INTR_WDH) ? " WDH" : "", - (mask & OHCI_INTR_SO) ? " SO" : ""); + dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", + label, + mask, + (mask & OHCI_INTR_MIE) ? " MIE" : "", + (mask & OHCI_INTR_OC) ? " OC" : "", + (mask & OHCI_INTR_RHSC) ? " RHSC" : "", + (mask & OHCI_INTR_FNO) ? " FNO" : "", + (mask & OHCI_INTR_UE) ? " UE" : "", + (mask & OHCI_INTR_RD) ? " RD" : "", + (mask & OHCI_INTR_SF) ? " SF" : "", + (mask & OHCI_INTR_WDH) ? " WDH" : "", + (mask & OHCI_INTR_SO) ? " SO" : "" + ); } -static void maybe_print_eds(char *label, __u32 value) +static void maybe_print_eds (char *label, __u32 value) { - ed_t *edp = (ed_t *) value; + ed_t *edp = (ed_t *)value; if (value) { - dbg("%s %08x", label, value); - dbg("%08x", edp->hwINFO); - dbg("%08x", edp->hwTailP); - dbg("%08x", edp->hwHeadP); - dbg("%08x", edp->hwNextED); + dbg ("%s %08x", label, value); + dbg ("%08x", edp->hwINFO); + dbg ("%08x", edp->hwTailP); + dbg ("%08x", edp->hwHeadP); + dbg ("%08x", edp->hwNextED); } } -static char *hcfs2string(int state) +static char * hcfs2string (int state) { switch (state) { - case OHCI_USB_RESET: - return "reset"; - case OHCI_USB_RESUME: - return "resume"; - case OHCI_USB_OPER: - return "operational"; - case OHCI_USB_SUSPEND: - return "suspend"; + case OHCI_USB_RESET: return "reset"; + case OHCI_USB_RESUME: return "resume"; + case OHCI_USB_OPER: return "operational"; + case OHCI_USB_SUSPEND: return "suspend"; } return "?"; } /* dump control and status registers */ -static void ohci_dump_status(ohci_t * controller) +static void ohci_dump_status (ohci_t *controller) { - struct ohci_regs *regs = controller->regs; - __u32 temp; + struct ohci_regs *regs = controller->regs; + __u32 temp; - temp = readl(®s->revision) & 0xff; + temp = readl (®s->revision) & 0xff; if (temp != 0x10) - dbg("spec %d.%d", (temp >> 4), (temp & 0x0f)); - - temp = readl(®s->control); - dbg("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, - (temp & OHCI_CTRL_RWE) ? " RWE" : "", - (temp & OHCI_CTRL_RWC) ? " RWC" : "", - (temp & OHCI_CTRL_IR) ? " IR" : "", - hcfs2string(temp & OHCI_CTRL_HCFS), - (temp & OHCI_CTRL_BLE) ? " BLE" : "", - (temp & OHCI_CTRL_CLE) ? " CLE" : "", - (temp & OHCI_CTRL_IE) ? " IE" : "", - (temp & OHCI_CTRL_PLE) ? " PLE" : "", temp & OHCI_CTRL_CBSR); - - temp = readl(®s->cmdstatus); - dbg("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, - (temp & OHCI_SOC) >> 16, - (temp & OHCI_OCR) ? " OCR" : "", - (temp & OHCI_BLF) ? " BLF" : "", - (temp & OHCI_CLF) ? " CLF" : "", (temp & OHCI_HCR) ? " HCR" : ""); - - ohci_dump_intr_mask("intrstatus", readl(®s->intrstatus)); - ohci_dump_intr_mask("intrenable", readl(®s->intrenable)); - - maybe_print_eds("ed_periodcurrent", readl(®s->ed_periodcurrent)); - - maybe_print_eds("ed_controlhead", readl(®s->ed_controlhead)); - maybe_print_eds("ed_controlcurrent", readl(®s->ed_controlcurrent)); - - maybe_print_eds("ed_bulkhead", readl(®s->ed_bulkhead)); - maybe_print_eds("ed_bulkcurrent", readl(®s->ed_bulkcurrent)); - - maybe_print_eds("donehead", readl(®s->donehead)); + dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); + + temp = readl (®s->control); + dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, + (temp & OHCI_CTRL_RWE) ? " RWE" : "", + (temp & OHCI_CTRL_RWC) ? " RWC" : "", + (temp & OHCI_CTRL_IR) ? " IR" : "", + hcfs2string (temp & OHCI_CTRL_HCFS), + (temp & OHCI_CTRL_BLE) ? " BLE" : "", + (temp & OHCI_CTRL_CLE) ? " CLE" : "", + (temp & OHCI_CTRL_IE) ? " IE" : "", + (temp & OHCI_CTRL_PLE) ? " PLE" : "", + temp & OHCI_CTRL_CBSR + ); + + temp = readl (®s->cmdstatus); + dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, + (temp & OHCI_SOC) >> 16, + (temp & OHCI_OCR) ? " OCR" : "", + (temp & OHCI_BLF) ? " BLF" : "", + (temp & OHCI_CLF) ? " CLF" : "", + (temp & OHCI_HCR) ? " HCR" : "" + ); + + ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); + ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); + + maybe_print_eds ("ed_periodcurrent", readl (®s->ed_periodcurrent)); + + maybe_print_eds ("ed_controlhead", readl (®s->ed_controlhead)); + maybe_print_eds ("ed_controlcurrent", readl (®s->ed_controlcurrent)); + + maybe_print_eds ("ed_bulkhead", readl (®s->ed_bulkhead)); + maybe_print_eds ("ed_bulkcurrent", readl (®s->ed_bulkcurrent)); + + maybe_print_eds ("donehead", readl (®s->donehead)); } -static void ohci_dump_roothub(ohci_t * controller, int verbose) +static void ohci_dump_roothub (ohci_t *controller, int verbose) { - __u32 temp, ndp, i; + __u32 temp, ndp, i; - temp = roothub_a(controller); + temp = roothub_a (controller); ndp = (temp & RH_A_NDP); if (verbose) { - dbg("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, - ((temp & RH_A_POTPGT) >> 24) & 0xff, - (temp & RH_A_NOCP) ? " NOCP" : "", - (temp & RH_A_OCPM) ? " OCPM" : "", - (temp & RH_A_DT) ? " DT" : "", - (temp & RH_A_NPS) ? " NPS" : "", - (temp & RH_A_PSM) ? " PSM" : "", ndp); - temp = roothub_b(controller); - dbg("roothub.b: %08x PPCM=%04x DR=%04x", - temp, (temp & RH_B_PPCM) >> 16, (temp & RH_B_DR) - ); - temp = roothub_status(controller); - dbg("roothub.status: %08x%s%s%s%s%s%s", - temp, - (temp & RH_HS_CRWE) ? " CRWE" : "", - (temp & RH_HS_OCIC) ? " OCIC" : "", - (temp & RH_HS_LPSC) ? " LPSC" : "", - (temp & RH_HS_DRWE) ? " DRWE" : "", - (temp & RH_HS_OCI) ? " OCI" : "", - (temp & RH_HS_LPS) ? " LPS" : ""); + dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, + ((temp & RH_A_POTPGT) >> 24) & 0xff, + (temp & RH_A_NOCP) ? " NOCP" : "", + (temp & RH_A_OCPM) ? " OCPM" : "", + (temp & RH_A_DT) ? " DT" : "", + (temp & RH_A_NPS) ? " NPS" : "", + (temp & RH_A_PSM) ? " PSM" : "", + ndp + ); + temp = roothub_b (controller); + dbg ("roothub.b: %08x PPCM=%04x DR=%04x", + temp, + (temp & RH_B_PPCM) >> 16, + (temp & RH_B_DR) + ); + temp = roothub_status (controller); + dbg ("roothub.status: %08x%s%s%s%s%s%s", + temp, + (temp & RH_HS_CRWE) ? " CRWE" : "", + (temp & RH_HS_OCIC) ? " OCIC" : "", + (temp & RH_HS_LPSC) ? " LPSC" : "", + (temp & RH_HS_DRWE) ? " DRWE" : "", + (temp & RH_HS_OCI) ? " OCI" : "", + (temp & RH_HS_LPS) ? " LPS" : "" + ); } for (i = 0; i < ndp; i++) { - temp = roothub_portstatus(controller, i); - dbg("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", - i, - temp, - (temp & RH_PS_PRSC) ? " PRSC" : "", - (temp & RH_PS_OCIC) ? " OCIC" : "", - (temp & RH_PS_PSSC) ? " PSSC" : "", - (temp & RH_PS_PESC) ? " PESC" : "", - (temp & RH_PS_CSC) ? " CSC" : "", - (temp & RH_PS_LSDA) ? " LSDA" : "", - (temp & RH_PS_PPS) ? " PPS" : "", - (temp & RH_PS_PRS) ? " PRS" : "", - (temp & RH_PS_POCI) ? " POCI" : "", - (temp & RH_PS_PSS) ? " PSS" : "", - (temp & RH_PS_PES) ? " PES" : "", - (temp & RH_PS_CCS) ? " CCS" : ""); + temp = roothub_portstatus (controller, i); + dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", + i, + temp, + (temp & RH_PS_PRSC) ? " PRSC" : "", + (temp & RH_PS_OCIC) ? " OCIC" : "", + (temp & RH_PS_PSSC) ? " PSSC" : "", + (temp & RH_PS_PESC) ? " PESC" : "", + (temp & RH_PS_CSC) ? " CSC" : "", + + (temp & RH_PS_LSDA) ? " LSDA" : "", + (temp & RH_PS_PPS) ? " PPS" : "", + (temp & RH_PS_PRS) ? " PRS" : "", + (temp & RH_PS_POCI) ? " POCI" : "", + (temp & RH_PS_PSS) ? " PSS" : "", + + (temp & RH_PS_PES) ? " PES" : "", + (temp & RH_PS_CCS) ? " CCS" : "" + ); } } -static void ohci_dump(ohci_t * controller, int verbose) +static void ohci_dump (ohci_t *controller, int verbose) { - dbg("OHCI controller usb-%s state", controller->slot_name); + dbg ("OHCI controller usb-%s state", controller->slot_name); /* dumps some of the state we know about */ - ohci_dump_status(controller); + ohci_dump_status (controller); if (verbose) - ep_print_int_eds(controller, "hcca"); - dbg("hcca frame #%04x", controller->hcca->frame_no); - ohci_dump_roothub(controller, 1); + ep_print_int_eds (controller, "hcca"); + dbg ("hcca frame #%04x", controller->hcca->frame_no); + ohci_dump_roothub (controller, 1); } -#endif /* DEBUG */ + +#endif /* DEBUG */ /*-------------------------------------------------------------------------* * Interface functions (URB) @@ -383,10 +388,10 @@ static void ohci_dump(ohci_t * controller, int verbose) /* get a transfer request */ int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, int interval) + int transfer_len, struct devrequest *setup, int interval) { ohci_t *ohci; - ed_t *ed; + ed_t * ed; urb_priv_t *purb_priv; int i, size = 0; @@ -399,20 +404,31 @@ int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, return -1; } + /* if we have an unfinished URB from previous transaction let's + * fail and scream as quickly as possible so as not to corrupt + * further communication */ + if (!urb_finished) { + err("sohci_submit_job: URB NOT FINISHED"); + return -1; + } + /* we're about to begin a new transaction here so mark the URB unfinished */ + urb_finished = 0; + /* every endpoint has a ed, locate and fill it */ - if (!(ed = ep_add_ed(dev, pipe))) { + if (!(ed = ep_add_ed (dev, pipe))) { err("sohci_submit_job: ENOMEM"); return -1; } /* for the private part of the URB we need the number of TDs (size) */ - switch (usb_pipetype(pipe)) { - case PIPE_BULK: /* one TD for every 4096 Byte */ - size = (transfer_len - 1) / 4096 + 1; - break; - case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ - size = (transfer_len == 0) ? 2 : (transfer_len - 1) / 4096 + 3; - break; + switch (usb_pipetype (pipe)) { + case PIPE_BULK: /* one TD for every 4096 Byte */ + size = (transfer_len - 1) / 4096 + 1; + break; + case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ + size = (transfer_len == 0)? 2: + (transfer_len - 1) / 4096 + 3; + break; } if (size >= (N_URB_TD - 1)) { @@ -430,28 +446,27 @@ int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, /* allocate the TDs */ /* note that td[0] was allocated in ep_add_ed */ for (i = 0; i < size; i++) { - purb_priv->td[i] = td_alloc(dev); + purb_priv->td[i] = td_alloc (dev); if (!purb_priv->td[i]) { purb_priv->length = i; - urb_free_priv(purb_priv); + urb_free_priv (purb_priv); err("sohci_submit_job: ENOMEM"); return -1; } } if (ed->state == ED_NEW || (ed->state & ED_DEL)) { - urb_free_priv(purb_priv); + urb_free_priv (purb_priv); err("sohci_submit_job: EINVAL"); return -1; } /* link the ed into a chain if is not already */ if (ed->state != ED_OPER) - ep_link(ohci, ed); + ep_link (ohci, ed); /* fill the TDs and link it to the ed */ - td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, - interval); + td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, interval); return 0; } @@ -461,11 +476,11 @@ int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, #ifdef DEBUG /* tell us the current USB frame number */ -static int sohci_get_current_frame_number(struct usb_device *usb_dev) +static int sohci_get_current_frame_number (struct usb_device *usb_dev) { ohci_t *ohci = &gohci; - return ohci_cpu_to_le16(ohci->hcca->frame_no); + return ohci_cpu_to_le16 (ohci->hcca->frame_no); } #endif @@ -475,7 +490,7 @@ static int sohci_get_current_frame_number(struct usb_device *usb_dev) /* link an ed into one of the HC chains */ -static int ep_link(ohci_t * ohci, ed_t * edi) +static int ep_link (ohci_t *ohci, ed_t *edi) { volatile ed_t *ed = edi; @@ -485,16 +500,15 @@ static int ep_link(ohci_t * ohci, ed_t * edi) case PIPE_CONTROL: ed->hwNextED = 0; if (ohci->ed_controltail == NULL) { - writel(ed, &ohci->regs->ed_controlhead); + writel (ed, &ohci->regs->ed_controlhead); } else { - ohci->ed_controltail->hwNextED = - ohci_cpu_to_le32((unsigned long)ed); + ohci->ed_controltail->hwNextED = ohci_cpu_to_le32 ((unsigned long)ed); } ed->ed_prev = ohci->ed_controltail; if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && - !ohci->ed_rm_list[1] && !ohci->sleeping) { + !ohci->ed_rm_list[1] && !ohci->sleeping) { ohci->hc_control |= OHCI_CTRL_CLE; - writel(ohci->hc_control, &ohci->regs->control); + writel (ohci->hc_control, &ohci->regs->control); } ohci->ed_controltail = edi; break; @@ -502,16 +516,15 @@ static int ep_link(ohci_t * ohci, ed_t * edi) case PIPE_BULK: ed->hwNextED = 0; if (ohci->ed_bulktail == NULL) { - writel(ed, &ohci->regs->ed_bulkhead); + writel (ed, &ohci->regs->ed_bulkhead); } else { - ohci->ed_bulktail->hwNextED = - ohci_cpu_to_le32((unsigned long)ed); + ohci->ed_bulktail->hwNextED = ohci_cpu_to_le32 ((unsigned long)ed); } ed->ed_prev = ohci->ed_bulktail; if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && - !ohci->ed_rm_list[1] && !ohci->sleeping) { + !ohci->ed_rm_list[1] && !ohci->sleeping) { ohci->hc_control |= OHCI_CTRL_BLE; - writel(ohci->hc_control, &ohci->regs->control); + writel (ohci->hc_control, &ohci->regs->control); } ohci->ed_bulktail = edi; break; @@ -526,30 +539,27 @@ static int ep_link(ohci_t * ohci, ed_t * edi) * the link from the ed still points to another operational ed or 0 * so the HC can eventually finish the processing of the unlinked ed */ -static int ep_unlink(ohci_t * ohci, ed_t * edi) +static int ep_unlink (ohci_t *ohci, ed_t *edi) { volatile ed_t *ed = edi; - ed->hwINFO |= ohci_cpu_to_le32(OHCI_ED_SKIP); + ed->hwINFO |= ohci_cpu_to_le32 (OHCI_ED_SKIP); switch (ed->type) { case PIPE_CONTROL: if (ed->ed_prev == NULL) { if (!ed->hwNextED) { ohci->hc_control &= ~OHCI_CTRL_CLE; - writel(ohci->hc_control, &ohci->regs->control); + writel (ohci->hc_control, &ohci->regs->control); } - writel(ohci_cpu_to_le32(*((__u32 *) & ed->hwNextED)), - &ohci->regs->ed_controlhead); + writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_controlhead); } else { ed->ed_prev->hwNextED = ed->hwNextED; } if (ohci->ed_controltail == ed) { ohci->ed_controltail = ed->ed_prev; } else { - ((ed_t *) - ohci_cpu_to_le32(*((__u32 *) & ed->hwNextED)))-> - ed_prev = ed->ed_prev; + ((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; } break; @@ -557,19 +567,16 @@ static int ep_unlink(ohci_t * ohci, ed_t * edi) if (ed->ed_prev == NULL) { if (!ed->hwNextED) { ohci->hc_control &= ~OHCI_CTRL_BLE; - writel(ohci->hc_control, &ohci->regs->control); + writel (ohci->hc_control, &ohci->regs->control); } - writel(ohci_cpu_to_le32(*((__u32 *) & ed->hwNextED)), - &ohci->regs->ed_bulkhead); + writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_bulkhead); } else { ed->ed_prev->hwNextED = ed->hwNextED; } if (ohci->ed_bulktail == ed) { ohci->ed_bulktail = ed->ed_prev; } else { - ((ed_t *) - ohci_cpu_to_le32(*((__u32 *) & ed->hwNextED)))-> - ed_prev = ed->ed_prev; + ((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; } break; } @@ -577,6 +584,7 @@ static int ep_unlink(ohci_t * ohci, ed_t * edi) return 0; } + /*-------------------------------------------------------------------------*/ /* add/reinit an endpoint; this should be done once at the usb_set_configuration command, @@ -585,15 +593,14 @@ static int ep_unlink(ohci_t * ohci, ed_t * edi) * in all other cases the state is left unchanged * the ed info fields are setted anyway even though most of them should not change */ -static ed_t *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe) +static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe) { td_t *td; ed_t *ed_ret; volatile ed_t *ed; - ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint(pipe) << 1) | - (usb_pipecontrol(pipe) ? 0 : - usb_pipeout(pipe))]; + ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint (pipe) << 1) | + (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]; if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { err("ep_add_ed: pending delete"); @@ -602,23 +609,22 @@ static ed_t *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe) } if (ed->state == ED_NEW) { - ed->hwINFO = ohci_cpu_to_le32(OHCI_ED_SKIP); /* skip ed */ + ed->hwINFO = ohci_cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */ /* dummy td; end of td list for ed */ - td = td_alloc(usb_dev); - ed->hwTailP = ohci_cpu_to_le32((unsigned long)td); + td = td_alloc (usb_dev); + ed->hwTailP = ohci_cpu_to_le32 ((unsigned long)td); ed->hwHeadP = ed->hwTailP; ed->state = ED_UNLINK; - ed->type = usb_pipetype(pipe); + ed->type = usb_pipetype (pipe); ohci_dev.ed_cnt++; } - ed->hwINFO = ohci_cpu_to_le32(usb_pipedevice(pipe) - | usb_pipeendpoint(pipe) << 7 - | (usb_pipeisoc(pipe) ? 0x8000 : 0) - | (usb_pipecontrol(pipe) ? 0 - : (usb_pipeout(pipe) ? 0x800 : 0x1000)) - | usb_pipeslow(pipe) << 13 | - usb_maxpacket(usb_dev, pipe) << 16); + ed->hwINFO = ohci_cpu_to_le32 (usb_pipedevice (pipe) + | usb_pipeendpoint (pipe) << 7 + | (usb_pipeisoc (pipe)? 0x8000: 0) + | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) + | usb_pipeslow (pipe) << 13 + | usb_maxpacket (usb_dev, pipe) << 16); return ed_ret; } @@ -629,11 +635,11 @@ static ed_t *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe) /* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ -static void td_fill(ohci_t * ohci, unsigned int info, - void *data, int len, - struct usb_device *dev, int index, urb_priv_t * urb_priv) +static void td_fill (ohci_t *ohci, unsigned int info, + void *data, int len, + struct usb_device *dev, int index, urb_priv_t *urb_priv) { - volatile td_t *td, *td_pt; + volatile td_t *td, *td_pt; #ifdef OHCI_FILL_TRACE int i; #endif @@ -643,37 +649,33 @@ static void td_fill(ohci_t * ohci, unsigned int info, return; } /* use this td as the next dummy */ - td_pt = urb_priv->td[index]; + td_pt = urb_priv->td [index]; td_pt->hwNextTD = 0; /* fill the old dummy TD */ - td = urb_priv->td[index] = - (td_t *) (ohci_cpu_to_le32(urb_priv->ed->hwTailP) & ~0xf); + td = urb_priv->td [index] = (td_t *)(ohci_cpu_to_le32 (urb_priv->ed->hwTailP) & ~0xf); td->ed = urb_priv->ed; td->next_dl_td = NULL; td->index = index; - td->data = (__u32) data; + td->data = (__u32)data; #ifdef OHCI_FILL_TRACE - if ((usb_pipetype(urb_priv->pipe) == PIPE_BULK) - && usb_pipeout(urb_priv->pipe)) { + if ((usb_pipetype(urb_priv->pipe) == PIPE_BULK) && usb_pipeout(urb_priv->pipe)) { for (i = 0; i < len; i++) - printf("td->data[%d] %#2x ", i, - ((unsigned char *)td->data)[i]); + printf("td->data[%d] %#2x ",i, ((unsigned char *)td->data)[i]); printf("\n"); } #endif if (!len) data = 0; - td->hwINFO = ohci_cpu_to_le32(info); - td->hwCBP = ohci_cpu_to_le32((unsigned long)data); + td->hwINFO = ohci_cpu_to_le32 (info); + td->hwCBP = ohci_cpu_to_le32 ((unsigned long)data); if (data) - td->hwBE = ohci_cpu_to_le32((unsigned long)(data + len - 1)); + td->hwBE = ohci_cpu_to_le32 ((unsigned long)(data + len - 1)); else td->hwBE = 0; - td->hwNextTD = ohci_cpu_to_le32((unsigned long)td_pt); - td->hwPSW[0] = ohci_cpu_to_le16(((__u32) data & 0x0FFF) | 0xE000); + td->hwNextTD = ohci_cpu_to_le32 ((unsigned long)td_pt); /* append to queue */ td->ed->hwTailP = td->hwNextTD; @@ -682,11 +684,8 @@ static void td_fill(ohci_t * ohci, unsigned int info, /*-------------------------------------------------------------------------*/ /* prepare all TDs of a transfer */ - -static void td_submit_job(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *setup, urb_priv_t * urb, - int interval) +static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval) { ohci_t *ohci = &gohci; int data_len = transfer_len; @@ -696,12 +695,11 @@ static void td_submit_job(struct usb_device *dev, unsigned long pipe, unsigned int toggle = 0; /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */ - if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { + if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { toggle = TD_T_TOGGLE; } else { toggle = TD_T_DATA0; - usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), - 1); + usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1); } urb->td_cnt = 0; if (data_len) @@ -709,42 +707,37 @@ static void td_submit_job(struct usb_device *dev, unsigned long pipe, else data = 0; - switch (usb_pipetype(pipe)) { + switch (usb_pipetype (pipe)) { case PIPE_BULK: - info = usb_pipeout(pipe) ? TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN; - while (data_len > 4096) { - td_fill(ohci, info | (cnt ? TD_T_TOGGLE : toggle), data, - 4096, dev, cnt, urb); - data += 4096; - data_len -= 4096; - cnt++; + info = usb_pipeout (pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; + while(data_len > 4096) { + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, dev, cnt, urb); + data += 4096; data_len -= 4096; cnt++; } - info = usb_pipeout(pipe) ? - TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN; - td_fill(ohci, info | (cnt ? TD_T_TOGGLE : toggle), data, - data_len, dev, cnt, urb); + info = usb_pipeout (pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, dev, cnt, urb); cnt++; if (!ohci->sleeping) - writel(OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ + writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ break; case PIPE_CONTROL: info = TD_CC | TD_DP_SETUP | TD_T_DATA0; - td_fill(ohci, info, setup, 8, dev, cnt++, urb); + td_fill (ohci, info, setup, 8, dev, cnt++, urb); if (data_len > 0) { - info = usb_pipeout(pipe) ? - TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R - | TD_DP_IN | TD_T_DATA1; + info = usb_pipeout (pipe)? + TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; /* NOTE: mishandles transfers >8K, some >4K */ - td_fill(ohci, info, data, data_len, dev, cnt++, urb); + td_fill (ohci, info, data, data_len, dev, cnt++, urb); } - info = usb_pipeout(pipe) ? - TD_CC | TD_DP_IN | TD_T_DATA1 : TD_CC | TD_DP_OUT | - TD_T_DATA1; - td_fill(ohci, info, data, 0, dev, cnt++, urb); + info = usb_pipeout (pipe)? + TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; + td_fill (ohci, info, data, 0, dev, cnt++, urb); if (!ohci->sleeping) - writel(OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ + writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ break; } if (urb->length != cnt) @@ -755,6 +748,7 @@ static void td_submit_job(struct usb_device *dev, unsigned long pipe, * Done List handling functions *-------------------------------------------------------------------------*/ + /* calculate the transfer length and update the urb */ static void dl_transfer_length(td_t * td) @@ -762,12 +756,13 @@ static void dl_transfer_length(td_t * td) __u32 tdINFO, tdBE, tdCBP; urb_priv_t *lurb_priv = &urb_priv; - tdINFO = ohci_cpu_to_le32(td->hwINFO); - tdBE = ohci_cpu_to_le32(td->hwBE); - tdCBP = ohci_cpu_to_le32(td->hwCBP); + tdINFO = ohci_cpu_to_le32 (td->hwINFO); + tdBE = ohci_cpu_to_le32 (td->hwBE); + tdCBP = ohci_cpu_to_le32 (td->hwCBP); - if (!(usb_pipetype(lurb_priv->pipe) == PIPE_CONTROL && - ((td->index == 0) || (td->index == lurb_priv->length - 1)))) { + + if (!(usb_pipetype (lurb_priv->pipe) == PIPE_CONTROL && + ((td->index == 0) || (td->index == lurb_priv->length - 1)))) { if (tdBE != 0) { if (td->hwCBP == 0) lurb_priv->actual_length += tdBE - td->data + 1; @@ -782,42 +777,31 @@ static void dl_transfer_length(td_t * td) /* replies to the request have to be on a FIFO basis so * we reverse the reversed done-list */ -static td_t *dl_reverse_done_list(ohci_t * ohci) +static td_t * dl_reverse_done_list (ohci_t *ohci) { __u32 td_list_hc; td_t *td_rev = NULL; td_t *td_list = NULL; urb_priv_t *lurb_priv = NULL; - td_list_hc = ohci_cpu_to_le32(ohci->hcca->done_head) & 0xfffffff0; + td_list_hc = ohci_cpu_to_le32 (ohci->hcca->done_head) & 0xfffffff0; ohci->hcca->done_head = 0; while (td_list_hc) { - td_list = (td_t *) td_list_hc; + td_list = (td_t *)td_list_hc; - if (TD_CC_GET(ohci_cpu_to_le32(td_list->hwINFO))) { + if (TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO))) { lurb_priv = &urb_priv; dbg(" USB-error/status: %x : %p", - TD_CC_GET(ohci_cpu_to_le32(td_list->hwINFO)), - td_list); - if (td_list->ed->hwHeadP & ohci_cpu_to_le32(0x1)) { - if (lurb_priv - && ((td_list->index + 1) < - lurb_priv->length)) { + TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO)), td_list); + if (td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x1)) { + if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) { td_list->ed->hwHeadP = - (lurb_priv-> - td[lurb_priv->length - - 1]-> - hwNextTD & - ohci_cpu_to_le32(0xfffffff0)) | - (td_list->ed-> - hwHeadP & ohci_cpu_to_le32(0x2)); - lurb_priv->td_cnt += - lurb_priv->length - td_list->index - - 1; + (lurb_priv->td[lurb_priv->length - 1]->hwNextTD & ohci_cpu_to_le32 (0xfffffff0)) | + (td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x2)); + lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1; } else - td_list->ed->hwHeadP &= - ohci_cpu_to_le32(0xfffffff2); + td_list->ed->hwHeadP &= ohci_cpu_to_le32 (0xfffffff2); } #ifdef CONFIG_MPC5200 td_list->hwNextTD = 0; @@ -826,7 +810,7 @@ static td_t *dl_reverse_done_list(ohci_t * ohci) td_list->next_dl_td = td_rev; td_rev = td_list; - td_list_hc = ohci_cpu_to_le32(td_list->hwNextTD) & 0xfffffff0; + td_list_hc = ohci_cpu_to_le32 (td_list->hwNextTD) & 0xfffffff0; } return td_list; } @@ -834,12 +818,12 @@ static td_t *dl_reverse_done_list(ohci_t * ohci) /*-------------------------------------------------------------------------*/ /* td done list */ -static int dl_done_list(ohci_t * ohci, td_t * td_list) +static int dl_done_list (ohci_t *ohci, td_t *td_list) { td_t *td_list_next = NULL; ed_t *ed; int cc = 0; - int stat = 0xff; + int stat = 0; /* urb_t *urb; */ urb_priv_t *lurb_priv; __u32 tdINFO, edHeadP, edTailP; @@ -848,29 +832,30 @@ static int dl_done_list(ohci_t * ohci, td_t * td_list) td_list_next = td_list->next_dl_td; lurb_priv = &urb_priv; - tdINFO = ohci_cpu_to_le32(td_list->hwINFO); + tdINFO = ohci_cpu_to_le32 (td_list->hwINFO); ed = td_list->ed; dl_transfer_length(td_list); /* error code of transfer */ - cc = TD_CC_GET(tdINFO); + cc = TD_CC_GET (tdINFO); if (++(lurb_priv->td_cnt) == lurb_priv->length) { if ((ed->state & (ED_OPER | ED_UNLINK)) - && (lurb_priv->state != URB_DEL)) { + && (lurb_priv->state != URB_DEL)) { dbg("ConditionCode %#x", cc); stat = cc_to_error[cc]; + urb_finished = 1; } } if (ed->state != ED_NEW) { - edHeadP = ohci_cpu_to_le32(ed->hwHeadP) & 0xfffffff0; - edTailP = ohci_cpu_to_le32(ed->hwTailP); + edHeadP = ohci_cpu_to_le32 (ed->hwHeadP) & 0xfffffff0; + edTailP = ohci_cpu_to_le32 (ed->hwTailP); /* unlink eds if they are not busy */ if ((edHeadP == edTailP) && (ed->state == ED_OPER)) - ep_unlink(ohci, ed); + ep_unlink (ohci, ed); } td_list = td_list_next; @@ -883,101 +868,107 @@ static int dl_done_list(ohci_t * ohci, td_t * td_list) *-------------------------------------------------------------------------*/ /* Device descriptor */ -static __u8 root_hub_dev_des[] = { - 0x12, /* __u8 bLength; */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x10, /* __u16 bcdUSB; v1.1 */ +static __u8 root_hub_dev_des[] = +{ + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x10, /* __u16 bcdUSB; v1.1 */ 0x01, - 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ - 0x00, /* __u8 bDeviceSubClass; */ - 0x00, /* __u8 bDeviceProtocol; */ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ - 0x00, /* __u16 idVendor; */ + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ 0x00, - 0x00, /* __u16 idProduct; */ + 0x00, /* __u16 idProduct; */ 0x00, - 0x00, /* __u16 bcdDevice; */ + 0x00, /* __u16 bcdDevice; */ 0x00, - 0x00, /* __u8 iManufacturer; */ - 0x01, /* __u8 iProduct; */ - 0x00, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ + 0x00, /* __u8 iManufacturer; */ + 0x01, /* __u8 iProduct; */ + 0x00, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ }; + /* Configuration descriptor */ -static __u8 root_hub_config_des[] = { - 0x09, /* __u8 bLength; */ - 0x02, /* __u8 bDescriptorType; Configuration */ - 0x19, /* __u16 wTotalLength; */ +static __u8 root_hub_config_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ 0x00, - 0x01, /* __u8 bNumInterfaces; */ - 0x01, /* __u8 bConfigurationValue; */ - 0x00, /* __u8 iConfiguration; */ - 0x40, /* __u8 bmAttributes; - Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ - 0x00, /* __u8 MaxPower; */ + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ /* interface */ - 0x09, /* __u8 if_bLength; */ - 0x04, /* __u8 if_bDescriptorType; Interface */ - 0x00, /* __u8 if_bInterfaceNumber; */ - 0x00, /* __u8 if_bAlternateSetting; */ - 0x01, /* __u8 if_bNumEndpoints; */ - 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ - 0x00, /* __u8 if_bInterfaceSubClass; */ - 0x00, /* __u8 if_bInterfaceProtocol; */ - 0x00, /* __u8 if_iInterface; */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ /* endpoint */ - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ 0x00, - 0xff /* __u8 ep_bInterval; 255 ms */ + 0xff /* __u8 ep_bInterval; 255 ms */ }; -static unsigned char root_hub_str_index0[] = { +static unsigned char root_hub_str_index0[] = +{ 0x04, /* __u8 bLength; */ 0x03, /* __u8 bDescriptorType; String-descriptor */ 0x09, /* __u8 lang ID */ 0x04, /* __u8 lang ID */ }; -static unsigned char root_hub_str_index1[] = { +static unsigned char root_hub_str_index1[] = +{ 28, /* __u8 bLength; */ 0x03, /* __u8 bDescriptorType; String-descriptor */ 'O', /* __u8 Unicode */ - 0, /* __u8 Unicode */ + 0, /* __u8 Unicode */ 'H', /* __u8 Unicode */ - 0, /* __u8 Unicode */ + 0, /* __u8 Unicode */ 'C', /* __u8 Unicode */ - 0, /* __u8 Unicode */ + 0, /* __u8 Unicode */ 'I', /* __u8 Unicode */ - 0, /* __u8 Unicode */ + 0, /* __u8 Unicode */ ' ', /* __u8 Unicode */ - 0, /* __u8 Unicode */ + 0, /* __u8 Unicode */ 'R', /* __u8 Unicode */ - 0, /* __u8 Unicode */ + 0, /* __u8 Unicode */ 'o', /* __u8 Unicode */ - 0, /* __u8 Unicode */ + 0, /* __u8 Unicode */ 'o', /* __u8 Unicode */ - 0, /* __u8 Unicode */ + 0, /* __u8 Unicode */ 't', /* __u8 Unicode */ - 0, /* __u8 Unicode */ + 0, /* __u8 Unicode */ ' ', /* __u8 Unicode */ - 0, /* __u8 Unicode */ + 0, /* __u8 Unicode */ 'H', /* __u8 Unicode */ - 0, /* __u8 Unicode */ + 0, /* __u8 Unicode */ 'u', /* __u8 Unicode */ - 0, /* __u8 Unicode */ + 0, /* __u8 Unicode */ 'b', /* __u8 Unicode */ - 0, /* __u8 Unicode */ + 0, /* __u8 Unicode */ }; /* Hub class-specific descriptor is constructed dynamically */ + /*-------------------------------------------------------------------------*/ #define OK(x) len = (x); break @@ -993,19 +984,20 @@ static unsigned char root_hub_str_index1[] = { /* request to virtual root hub */ -int rh_check_port_status(ohci_t * controller) +int rh_check_port_status(ohci_t *controller) { __u32 temp, ndp, i; int res; res = -1; - temp = roothub_a(controller); + temp = roothub_a (controller); ndp = (temp & RH_A_NDP); for (i = 0; i < ndp; i++) { - temp = roothub_portstatus(controller, i); + temp = roothub_portstatus (controller, i); /* check for a device disconnect */ if (((temp & (RH_PS_PESC | RH_PS_CSC)) == - (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0)) { + (RH_PS_PESC | RH_PS_CSC)) && + ((temp & RH_PS_CCS) == 0)) { res = i; break; } @@ -1014,235 +1006,209 @@ int rh_check_port_status(ohci_t * controller) } static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *cmd) + void *buffer, int transfer_len, struct devrequest *cmd) { - void *data = buffer; + void * data = buffer; int leni = transfer_len; int len = 0; int stat = 0; __u32 datab[4]; - __u8 *data_buf = (__u8 *) datab; + __u8 *data_buf = (__u8 *)datab; __u16 bmRType_bReq; __u16 wValue; __u16 wIndex; __u16 wLength; #ifdef DEBUG - urb_priv.actual_length = 0; - pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", - usb_pipein(pipe)); +urb_priv.actual_length = 0; +pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe)); #endif if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { info("Root-Hub submit IRQ: NOT implemented"); return 0; } - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = m16_swap(cmd->value); - wIndex = m16_swap(cmd->index); - wLength = m16_swap(cmd->length); + bmRType_bReq = cmd->requesttype | (cmd->request << 8); + wValue = m16_swap (cmd->value); + wIndex = m16_swap (cmd->index); + wLength = m16_swap (cmd->length); info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", - dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); + dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); switch (bmRType_bReq) { - /* Request Destination: - without flags: Device, - RH_INTERFACE: interface, - RH_ENDPOINT: endpoint, - RH_CLASS means HUB here, - RH_OTHER | RH_CLASS almost ever means HUB_PORT here - */ + /* Request Destination: + without flags: Device, + RH_INTERFACE: interface, + RH_ENDPOINT: endpoint, + RH_CLASS means HUB here, + RH_OTHER | RH_CLASS almost ever means HUB_PORT here + */ case RH_GET_STATUS: - *(__u16 *) data_buf = m16_swap(1); - OK(2); + *(__u16 *) data_buf = m16_swap (1); OK (2); case RH_GET_STATUS | RH_INTERFACE: - *(__u16 *) data_buf = m16_swap(0); - OK(2); + *(__u16 *) data_buf = m16_swap (0); OK (2); case RH_GET_STATUS | RH_ENDPOINT: - *(__u16 *) data_buf = m16_swap(0); - OK(2); + *(__u16 *) data_buf = m16_swap (0); OK (2); case RH_GET_STATUS | RH_CLASS: - *(__u32 *) data_buf = - m32_swap(RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); - OK(4); + *(__u32 *) data_buf = m32_swap ( + RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); + OK (4); case RH_GET_STATUS | RH_OTHER | RH_CLASS: - *(__u32 *) data_buf = m32_swap(RD_RH_PORTSTAT); - OK(4); + *(__u32 *) data_buf = m32_swap (RD_RH_PORTSTAT); OK (4); case RH_CLEAR_FEATURE | RH_ENDPOINT: switch (wValue) { - case (RH_ENDPOINT_STALL): - OK(0); + case (RH_ENDPOINT_STALL): OK (0); } break; case RH_CLEAR_FEATURE | RH_CLASS: switch (wValue) { - case RH_C_HUB_LOCAL_POWER: - OK(0); - case (RH_C_HUB_OVER_CURRENT): - WR_RH_STAT(RH_HS_OCIC); - OK(0); + case RH_C_HUB_LOCAL_POWER: + OK(0); + case (RH_C_HUB_OVER_CURRENT): + WR_RH_STAT(RH_HS_OCIC); OK (0); } break; case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: switch (wValue) { - case (RH_PORT_ENABLE): - WR_RH_PORTSTAT(RH_PS_CCS); - OK(0); - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT(RH_PS_POCI); - OK(0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT(RH_PS_LSDA); - OK(0); - case (RH_C_PORT_CONNECTION): - WR_RH_PORTSTAT(RH_PS_CSC); - OK(0); - case (RH_C_PORT_ENABLE): - WR_RH_PORTSTAT(RH_PS_PESC); - OK(0); - case (RH_C_PORT_SUSPEND): - WR_RH_PORTSTAT(RH_PS_PSSC); - OK(0); - case (RH_C_PORT_OVER_CURRENT): - WR_RH_PORTSTAT(RH_PS_OCIC); - OK(0); - case (RH_C_PORT_RESET): - WR_RH_PORTSTAT(RH_PS_PRSC); - OK(0); + case (RH_PORT_ENABLE): + WR_RH_PORTSTAT (RH_PS_CCS ); OK (0); + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_POCI); OK (0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT (RH_PS_LSDA); OK (0); + case (RH_C_PORT_CONNECTION): + WR_RH_PORTSTAT (RH_PS_CSC ); OK (0); + case (RH_C_PORT_ENABLE): + WR_RH_PORTSTAT (RH_PS_PESC); OK (0); + case (RH_C_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_PSSC); OK (0); + case (RH_C_PORT_OVER_CURRENT): + WR_RH_PORTSTAT (RH_PS_OCIC); OK (0); + case (RH_C_PORT_RESET): + WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); } break; case RH_SET_FEATURE | RH_OTHER | RH_CLASS: switch (wValue) { - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT(RH_PS_PSS); - OK(0); - case (RH_PORT_RESET): /* BUG IN HUP CODE ******** */ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT(RH_PS_PRS); - OK(0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT(RH_PS_PPS); - OK(0); - case (RH_PORT_ENABLE): /* BUG IN HUP CODE ******** */ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT(RH_PS_PES); - OK(0); + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); + case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT (RH_PS_PRS); + OK (0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); + case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT (RH_PS_PES ); + OK (0); } break; - case RH_SET_ADDRESS: - gohci.rh.devnum = wValue; - OK(0); + case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0); case RH_GET_DESCRIPTOR: switch ((wValue & 0xff00) >> 8) { - case (0x01): /* device descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_dev_des), wLength)); - data_buf = root_hub_dev_des; - OK(len); - case (0x02): /* configuration descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_config_des), - wLength)); - data_buf = root_hub_config_des; - OK(len); - case (0x03): /* string descriptors */ - if (wValue == 0x0300) { + case (0x01): /* device descriptor */ len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_str_index0), - wLength)); - data_buf = root_hub_str_index0; - OK(len); - } - if (wValue == 0x0301) { + leni, + min_t(unsigned int, + sizeof (root_hub_dev_des), + wLength)); + data_buf = root_hub_dev_des; OK(len); + case (0x02): /* configuration descriptor */ len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_str_index1), - wLength)); - data_buf = root_hub_str_index1; - OK(len); + leni, + min_t(unsigned int, + sizeof (root_hub_config_des), + wLength)); + data_buf = root_hub_config_des; OK(len); + case (0x03): /* string descriptors */ + if(wValue==0x0300) { + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_str_index0), + wLength)); + data_buf = root_hub_str_index0; + OK(len); + } + if(wValue==0x0301) { + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_str_index1), + wLength)); + data_buf = root_hub_str_index1; + OK(len); } - default: - stat = USB_ST_STALLED; + default: + stat = USB_ST_STALLED; } break; case RH_GET_DESCRIPTOR | RH_CLASS: - { - __u32 temp = roothub_a(&gohci); - - data_buf[0] = 9; /* min length; */ - data_buf[1] = 0x29; - data_buf[2] = temp & RH_A_NDP; - data_buf[3] = 0; - if (temp & RH_A_PSM) /* per-port power switching? */ - data_buf[3] |= 0x1; - if (temp & RH_A_NOCP) /* no overcurrent reporting? */ - data_buf[3] |= 0x10; - else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */ - data_buf[3] |= 0x8; - - /* corresponds to data_buf[4-7] */ - datab[1] = 0; - data_buf[5] = (temp & RH_A_POTPGT) >> 24; - temp = roothub_b(&gohci); - data_buf[7] = temp & RH_B_DR; - if (data_buf[2] < 7) { - data_buf[8] = 0xff; - } else { - data_buf[0] += 2; - data_buf[8] = (temp & RH_B_DR) >> 8; - data_buf[10] = data_buf[9] = 0xff; - } - - len = min_t(unsigned int, leni, - min_t(unsigned int, data_buf[0], wLength)); - OK(len); + { + __u32 temp = roothub_a (&gohci); + + data_buf [0] = 9; /* min length; */ + data_buf [1] = 0x29; + data_buf [2] = temp & RH_A_NDP; + data_buf [3] = 0; + if (temp & RH_A_PSM) /* per-port power switching? */ + data_buf [3] |= 0x1; + if (temp & RH_A_NOCP) /* no overcurrent reporting? */ + data_buf [3] |= 0x10; + else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */ + data_buf [3] |= 0x8; + + /* corresponds to data_buf[4-7] */ + datab [1] = 0; + data_buf [5] = (temp & RH_A_POTPGT) >> 24; + temp = roothub_b (&gohci); + data_buf [7] = temp & RH_B_DR; + if (data_buf [2] < 7) { + data_buf [8] = 0xff; + } else { + data_buf [0] += 2; + data_buf [8] = (temp & RH_B_DR) >> 8; + data_buf [10] = data_buf [9] = 0xff; + } + + len = min_t(unsigned int, leni, + min_t(unsigned int, data_buf [0], wLength)); + OK (len); } - case RH_GET_CONFIGURATION: - *(__u8 *) data_buf = 0x01; - OK(1); + case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1); - case RH_SET_CONFIGURATION: - WR_RH_STAT(0x10000); - OK(0); + case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0); default: - dbg("unsupported root hub command"); + dbg ("unsupported root hub command"); stat = USB_ST_STALLED; } #ifdef DEBUG - ohci_dump_roothub(&gohci, 1); + ohci_dump_roothub (&gohci, 1); #endif len = min_t(int, len, leni); if (data != data_buf) - memcpy(data, data_buf, len); + memcpy (data, data_buf, len); dev->act_len = len; dev->status = stat; #ifdef DEBUG if (transfer_len) urb_priv.actual_length = transfer_len; - pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", - 0 /*usb_pipein(pipe) */ ); + pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); #endif return stat; @@ -1253,7 +1219,7 @@ static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, /* common code for handling submit messages - used for all but root hub */ /* accesses. */ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, int interval) + int transfer_len, struct devrequest *setup, int interval) { int stat = 0; int maxsize = usb_maxpacket(dev, pipe); @@ -1264,26 +1230,25 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, dev->status = USB_ST_CRC_ERR; return 0; } + #ifdef DEBUG urb_priv.actual_length = 0; - pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", - usb_pipein(pipe)); + pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); #endif if (!maxsize) { err("submit_common_message: pipesize for pipe %lx is zero", - pipe); + pipe); return -1; } - if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < - 0) { + if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < 0) { err("sohci_submit_job failed"); return -1; } /* allow more time for a BULK device to react - some are slow */ -#define BULK_TO 5000 /* timeout in milliseconds */ - if (usb_pipetype(pipe) == PIPE_BULK) +#define BULK_TO 5000 /* timeout in milliseconds */ + if (usb_pipetype (pipe) == PIPE_BULK) timeout = BULK_TO; else timeout = 100; @@ -1296,28 +1261,45 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, stat = USB_ST_CRC_ERR; break; } - if (stat >= 0 && stat < 0xff) { + + /* NOTE: since we are not interrupt driven in U-Boot and always + * handle only one URB at a time, we cannot assume the + * transaction finished on the first successful return from + * hc_interrupt().. unless the flag for current URB is set, + * meaning that all TD's to/from device got actually + * transferred and processed. If the current URB is not + * finished we need to re-iterate this loop so as + * hc_interrupt() gets called again as there needs to be some + * more TD's to process still */ + if ((stat >= 0) && (stat != 0xff) && (urb_finished)) { /* 0xff is returned for an SF-interrupt */ break; } + if (--timeout) { wait_ms(1); + if (!urb_finished) + dbg("\%"); + } else { err("CTL:TIMEOUT "); + dbg("submit_common_msg: TO status %x\n", stat); stat = USB_ST_CRC_ERR; + urb_finished = 1; break; } } +#if 0 /* we got an Root Hub Status Change interrupt */ if (got_rhsc) { #ifdef DEBUG - ohci_dump_roothub(&gohci, 1); + ohci_dump_roothub (&gohci, 1); #endif got_rhsc = 0; /* abuse timeout */ timeout = rh_check_port_status(&gohci); if (timeout >= 0) { -#if 0 /* this does nothing useful, but leave it here in case that changes */ +#if 0 /* this does nothing useful, but leave it here in case that changes */ /* the called routine adds 1 to the passed value */ usb_hub_port_connect_change(gohci.rh.dev, timeout - 1); #endif @@ -1329,56 +1311,55 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, devgone = dev; } } +#endif dev->status = stat; dev->act_len = transfer_len; #ifdef DEBUG - pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", - usb_pipein(pipe)); + pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe)); #endif /* free TDs in urb_priv */ - urb_free_priv(&urb_priv); + urb_free_priv (&urb_priv); return 0; } /* submit routines called from usb.c */ int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len) + int transfer_len) { info("submit_bulk_msg"); return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0); } int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup) + int transfer_len, struct devrequest *setup) { int maxsize = usb_maxpacket(dev, pipe); info("submit_control_msg"); #ifdef DEBUG urb_priv.actual_length = 0; - pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", - usb_pipein(pipe)); + pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); #endif if (!maxsize) { err("submit_control_message: pipesize for pipe %lx is zero", - pipe); + pipe); return -1; } if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) { gohci.rh.dev = dev; /* root hub - redirect */ return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len, - setup); + setup); } return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0); } int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, int interval) + int transfer_len, int interval) { info("submit_int_msg"); return -1; @@ -1390,16 +1371,16 @@ int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, /* reset the HC and BUS */ -static int hc_reset(ohci_t * ohci) +static int hc_reset (ohci_t *ohci) { int timeout = 30; - int smm_timeout = 50; /* 0,5 sec */ + int smm_timeout = 50; /* 0,5 sec */ - if (readl(&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ - writel(OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */ + if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ + writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */ info("USB HC TakeOver from SMM"); - while (readl(&ohci->regs->control) & OHCI_CTRL_IR) { - wait_ms(10); + while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { + wait_ms (10); if (--smm_timeout == 0) { err("USB HC TakeOver failed!"); return -1; @@ -1408,23 +1389,24 @@ static int hc_reset(ohci_t * ohci) } /* Disable HC interrupts */ - writel(OHCI_INTR_MIE, &ohci->regs->intrdisable); + writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;", - ohci->slot_name, readl(&ohci->regs->control)); + ohci->slot_name, + readl (&ohci->regs->control)); /* Reset USB (needed by some controllers) */ ohci->hc_control = 0; - writel(ohci->hc_control, &ohci->regs->control); + writel (ohci->hc_control, &ohci->regs->control); /* HC Reset requires max 10 us delay */ - writel(OHCI_HCR, &ohci->regs->cmdstatus); - while ((readl(&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { + writel (OHCI_HCR, &ohci->regs->cmdstatus); + while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { if (--timeout == 0) { err("USB HC reset timed out!"); return -1; } - udelay(1); + udelay (1); } return 0; } @@ -1435,7 +1417,7 @@ static int hc_reset(ohci_t * ohci) * enable interrupts * connect the virtual root hub */ -static int hc_start(ohci_t * ohci) +static int hc_start (ohci_t * ohci) { __u32 mask; unsigned int fminterval; @@ -1445,44 +1427,44 @@ static int hc_start(ohci_t * ohci) /* Tell the controller where the control and bulk lists are * The lists are empty now. */ - writel(0, &ohci->regs->ed_controlhead); - writel(0, &ohci->regs->ed_bulkhead); + writel (0, &ohci->regs->ed_controlhead); + writel (0, &ohci->regs->ed_bulkhead); - writel((__u32) ohci->hcca, &ohci->regs->hcca); /* a reset clears this */ + writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */ fminterval = 0x2edf; - writel((fminterval * 9) / 10, &ohci->regs->periodicstart); + writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); fminterval |= ((((fminterval - 210) * 6) / 7) << 16); - writel(fminterval, &ohci->regs->fminterval); - writel(0x628, &ohci->regs->lsthresh); + writel (fminterval, &ohci->regs->fminterval); + writel (0x628, &ohci->regs->lsthresh); /* start controller operations */ ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; ohci->disabled = 0; - writel(ohci->hc_control, &ohci->regs->control); + writel (ohci->hc_control, &ohci->regs->control); /* disable all interrupts */ mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD | - OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC | - OHCI_INTR_OC | OHCI_INTR_MIE); - writel(mask, &ohci->regs->intrdisable); + OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC | + OHCI_INTR_OC | OHCI_INTR_MIE); + writel (mask, &ohci->regs->intrdisable); /* clear all interrupts */ mask &= ~OHCI_INTR_MIE; - writel(mask, &ohci->regs->intrstatus); + writel (mask, &ohci->regs->intrstatus); /* Choose the interrupts we care about now - but w/o MIE */ mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; - writel(mask, &ohci->regs->intrenable); + writel (mask, &ohci->regs->intrenable); #ifdef OHCI_USE_NPS /* required for AMD-756 and some Mac platforms */ - writel((roothub_a(ohci) | RH_A_NPS) & ~RH_A_PSM, - &ohci->regs->roothub.a); - writel(RH_HS_LPSC, &ohci->regs->roothub.status); -#endif /* OHCI_USE_NPS */ + writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM, + &ohci->regs->roothub.a); + writel (RH_HS_LPSC, &ohci->regs->roothub.status); +#endif /* OHCI_USE_NPS */ #define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);}) /* POTPGT delay is bits 24-31, in 2 ms units. */ - mdelay((roothub_a(ohci) >> 23) & 0x1fe); + mdelay ((roothub_a (ohci) >> 23) & 0x1fe); /* connect the virtual root hub */ ohci->rh.devnum = 0; @@ -1494,65 +1476,76 @@ static int hc_start(ohci_t * ohci) /* an interrupt happens */ -static int hc_interrupt(void) +static int +hc_interrupt (void) { ohci_t *ohci = &gohci; struct ohci_regs *regs = ohci->regs; int ints; int stat = -1; - if ((ohci->hcca->done_head != 0) - && !(ohci_cpu_to_le32(ohci->hcca->done_head) & 0x01)) { - ints = OHCI_INTR_WDH; - } else { - ints = readl(®s->intrstatus); + if ((ohci->hcca->done_head != 0) && + !(ohci_cpu_to_le32(ohci->hcca->done_head) & 0x01)) { + + ints = OHCI_INTR_WDH; + + } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { + ohci->disabled++; + err ("%s device removed!", ohci->slot_name); + return -1; + + } else if ((ints &= readl (®s->intrenable)) == 0) { + dbg("hc_interrupt: returning..\n"); + return 0xff; } /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */ if (ints & OHCI_INTR_RHSC) { got_rhsc = 1; + stat = 0xff; } if (ints & OHCI_INTR_UE) { ohci->disabled++; - err("OHCI Unrecoverable Error, controller usb-%s disabled", - ohci->slot_name); + err ("OHCI Unrecoverable Error, controller usb-%s disabled", + ohci->slot_name); /* e.g. due to PCI Master/Target Abort */ #ifdef DEBUG - ohci_dump(ohci, 1); + ohci_dump (ohci, 1); #endif /* FIXME: be optimistic, hope that bug won't repeat often. */ /* Make some non-interrupt context restart the controller. */ /* Count and limit the retries though; either hardware or */ /* software errors can go forever... */ - hc_reset(ohci); + hc_reset (ohci); return -1; } if (ints & OHCI_INTR_WDH) { - writel(OHCI_INTR_WDH, ®s->intrdisable); - stat = dl_done_list(&gohci, dl_reverse_done_list(&gohci)); - writel(OHCI_INTR_WDH, ®s->intrenable); + writel (OHCI_INTR_WDH, ®s->intrdisable); + stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci)); + writel (OHCI_INTR_WDH, ®s->intrenable); } if (ints & OHCI_INTR_SO) { dbg("USB Schedule overrun\n"); - writel(OHCI_INTR_SO, ®s->intrenable); + writel (OHCI_INTR_SO, ®s->intrenable); stat = -1; } /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */ if (ints & OHCI_INTR_SF) { - unsigned int frame = ohci_cpu_to_le16(ohci->hcca->frame_no) & 1; - writel(OHCI_INTR_SF, ®s->intrdisable); + unsigned int frame = ohci_cpu_to_le16 (ohci->hcca->frame_no) & 1; + wait_ms(1); + writel (OHCI_INTR_SF, ®s->intrdisable); if (ohci->ed_rm_list[frame] != NULL) - writel(OHCI_INTR_SF, ®s->intrenable); + writel (OHCI_INTR_SF, ®s->intrenable); stat = 0xff; } - writel(ints, ®s->intrstatus); + writel (ints, ®s->intrstatus); return stat; } @@ -1562,12 +1555,12 @@ static int hc_interrupt(void) /* De-allocate all resources.. */ -static void hc_release_ohci(ohci_t * ohci) +static void hc_release_ohci (ohci_t *ohci) { - dbg("USB HC release ohci usb-%s", ohci->slot_name); + dbg ("USB HC release ohci usb-%s", ohci->slot_name); if (!ohci->disabled) - hc_reset(ohci); + hc_reset (ohci); } /*-------------------------------------------------------------------------*/ @@ -1579,30 +1572,29 @@ static char ohci_inited = 0; int usb_lowlevel_init(void) { - - memset(&gohci, 0, sizeof(ohci_t)); - memset(&urb_priv, 0, sizeof(urb_priv_t)); + memset (&gohci, 0, sizeof (ohci_t)); + memset (&urb_priv, 0, sizeof (urb_priv_t)); /* align the storage */ - if ((__u32) & ghcca[0] & 0xff) { + if ((__u32)&ghcca[0] & 0xff) { err("HCCA not aligned!!"); return -1; } phcca = &ghcca[0]; info("aligned ghcca %p", phcca); memset(&ohci_dev, 0, sizeof(struct ohci_device)); - if ((__u32) & ohci_dev.ed[0] & 0x7) { + if ((__u32)&ohci_dev.ed[0] & 0x7) { err("EDs not aligned!!"); return -1; } memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1)); - if ((__u32) gtd & 0x7) { + if ((__u32)gtd & 0x7) { err("TDs not aligned!!"); return -1; } ptd = gtd; gohci.hcca = phcca; - memset(phcca, 0, sizeof(struct ohci_hcca)); + memset (phcca, 0, sizeof (struct ohci_hcca)); gohci.disabled = 1; gohci.sleeping = 0; @@ -1612,20 +1604,22 @@ int usb_lowlevel_init(void) gohci.flags = 0; gohci.slot_name = "ppc440"; - if (hc_reset(&gohci) < 0) { - hc_release_ohci(&gohci); + if (hc_reset (&gohci) < 0) { + hc_release_ohci (&gohci); return -1; } - if (hc_start(&gohci) < 0) { - err("can't start usb-%s", gohci.slot_name); - hc_release_ohci(&gohci); + if (hc_start (&gohci) < 0) { + err ("can't start usb-%s", gohci.slot_name); + hc_release_ohci (&gohci); return -1; } + #ifdef DEBUG - ohci_dump(&gohci, 1); + ohci_dump (&gohci, 1); #endif ohci_inited = 1; + urb_finished = 1; /* init the device driver */ usb_dev_init(); @@ -1641,8 +1635,8 @@ int usb_lowlevel_stop(void) return 0; /* TODO release any interrupts, etc. */ /* call hc_release_ohci() here ? */ - hc_reset(&gohci); + hc_reset (&gohci); return 0; } -#endif /* CONFIG_USB_OHCI */ +#endif /* CONFIG_USB_OHCI */ |