[U-Boot] [patch 0/3] Improve stability USB memory sticks for the common OHCI USB layer.

This series is a set of patches that are required to make USB sticks behave robust while using U-Boot on a OHCI host.
Several users complain about ERROR: CTL:TIMEOUT errors while using USB sticks, and while testing many different USB sticks it showed that some were working and many don't. It even showed a compiler dependency while debugging this, where GCC 3.x compilers seemed to work (but not always) and GCC 4.x compilers usually don't. While debugging this (with a USB analyser of course) it turned out that U-boot also made several protocol violations that needed to be solved, these resulted in hanging USB devices and so on.
In a mail thread with Stelian Pop on 28 July it was reported of a known error on Atmel cores that it did not work.
I tested these series on Atmel AT91SAM9261 Core, with the common OHCI driver, GCC 4.2.3 (Code Sourcery G++ Lite 2008q1-126)
REMEMBER: U-boot still supports 1 single USB stick at a time...

The GCC-compiler makes an optimisation error while optimising the routine usb_set_maxpacket(). This should be fixed in the compiler in the first place, but there lots of compilers out there that makes this error, that it is probably wiser to workaround it in U-boot itself.
What happens is that the register r3 is used as loop-counter 'i', but gets overwritten later on. From there it starts using register r3 for several other things and the assembler code is becoming a big mess. This is clearly a compiler bug.
This error occurs on at least several versions of Code Sourcery Lite compilers for ARM. Like the Edition 2008q1, and 2008q3, It has also been seen on other compilers, while compiling for armv4t, or armv5te with Os, O1 and O2.
We work around it by splitting up this routine in 2 parts, and making sure that the split out part is NOT inlined any longer. This will make GCC spit out assembler that do not show this problem. Another possibility is to adapt the Makefile to stop optimisation for the complete file. I think this solution is nicer.
Signed-off-by: Remy Bohmer linux@bohmer.net --- common/usb.c | 73 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 27 deletions(-)
Index: u-boot-git-18082008/common/usb.c =================================================================== --- u-boot-git-18082008.orig/common/usb.c 2008-09-16 11:30:16.000000000 +0200 +++ u-boot-git-18082008/common/usb.c 2008-09-16 11:58:06.000000000 +0200 @@ -245,40 +245,59 @@ int usb_maxpacket(struct usb_device *dev return(dev->epmaxpacketin[((pipe>>15) & 0xf)]); }
+/* The routine usb_set_maxpacket_ep() is extracted from the loop of routine + * usb_set_maxpacket(), because the optimizer of GCC 4.x chokes on this routine + * when it is inlined in 1 single routine. What happens is that the register r3 + * is used as loop-count 'i', but gets overwritten later on. + * This is clearly a compiler bug, but it is easier to workaround it here than + * to update the compiler (Occurs with at least several GCC 4.{1,2},x + * CodeSourcery compilers like e.g. 2007q3, 2008q1, 2008q3 lite editions on ARM) + */ +static void __attribute__((noinline)) +usb_set_maxpacket_ep(struct usb_device *dev, struct usb_endpoint_descriptor *ep) +{ + int b; + + b = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + + if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL) { + /* Control => bidirectional */ + dev->epmaxpacketout[b] = ep->wMaxPacketSize; + dev->epmaxpacketin [b] = ep->wMaxPacketSize; + USB_PRINTF("##Control EP epmaxpacketout/in[%d] = %d\n", + b, dev->epmaxpacketin[b]); + } else { + if ((ep->bEndpointAddress & 0x80) == 0) { + /* OUT Endpoint */ + if (ep->wMaxPacketSize > dev->epmaxpacketout[b]) { + dev->epmaxpacketout[b] = ep->wMaxPacketSize; + USB_PRINTF("##EP epmaxpacketout[%d] = %d\n", + b, dev->epmaxpacketout[b]); + } + } else { + /* IN Endpoint */ + if (ep->wMaxPacketSize > dev->epmaxpacketin[b]) { + dev->epmaxpacketin[b] = ep->wMaxPacketSize; + USB_PRINTF("##EP epmaxpacketin[%d] = %d\n", + b, dev->epmaxpacketin[b]); + } + } /* if out */ + } /* if control */ +} + /* * set the max packed value of all endpoints in the given configuration */ int usb_set_maxpacket(struct usb_device *dev) { - int i,ii,b; - struct usb_endpoint_descriptor *ep; + int i, ii;
- for(i=0; i<dev->config.bNumInterfaces;i++) { - for(ii=0; ii<dev->config.if_desc[i].bNumEndpoints; ii++) { - ep = &dev->config.if_desc[i].ep_desc[ii]; - b=ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + for (i = 0; i < dev->config.bNumInterfaces; i++) + for (ii = 0; ii < dev->config.if_desc[i].bNumEndpoints; ii++) + usb_set_maxpacket_ep(dev, + &dev->config.if_desc[i].ep_desc[ii]);
- if((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)==USB_ENDPOINT_XFER_CONTROL) { /* Control => bidirectional */ - dev->epmaxpacketout[b] = ep->wMaxPacketSize; - dev->epmaxpacketin [b] = ep->wMaxPacketSize; - USB_PRINTF("##Control EP epmaxpacketout/in[%d] = %d\n",b,dev->epmaxpacketin[b]); - } - else { - if ((ep->bEndpointAddress & 0x80)==0) { /* OUT Endpoint */ - if(ep->wMaxPacketSize > dev->epmaxpacketout[b]) { - dev->epmaxpacketout[b] = ep->wMaxPacketSize; - USB_PRINTF("##EP epmaxpacketout[%d] = %d\n",b,dev->epmaxpacketout[b]); - } - } - else { /* IN Endpoint */ - if(ep->wMaxPacketSize > dev->epmaxpacketin[b]) { - dev->epmaxpacketin[b] = ep->wMaxPacketSize; - USB_PRINTF("##EP epmaxpacketin[%d] = %d\n",b,dev->epmaxpacketin[b]); - } - } /* if out */ - } /* if control */ - } /* for each endpoint */ - } return 0; }

This patch refactors some large routines of the USB OHCI code by making some routines smaller and more readable which helps debugging and understanding the code. (Makes the code looks somewhat more like the Linux implementation.)
Also made entire file compliant to Linux Coding Rules (checkpatch.pl compliant)
Signed-off-by: Remy Bohmer linux@bohmer.net --- common/usb.c | 544 +++++++++++++++------------ drivers/usb/usb_ohci.c | 972 ++++++++++++++++++++++++++----------------------- drivers/usb/usb_ohci.h | 35 + 3 files changed, 863 insertions(+), 688 deletions(-)
Index: u-boot/common/usb.c =================================================================== --- u-boot.orig/common/usb.c 2008-09-16 14:38:57.000000000 +0200 +++ u-boot/common/usb.c 2008-09-16 14:39:24.000000000 +0200 @@ -58,9 +58,9 @@ #undef USB_DEBUG
#ifdef USB_DEBUG -#define USB_PRINTF(fmt,args...) printf (fmt ,##args) +#define USB_PRINTF(fmt, args...) printf (fmt , ##args) #else -#define USB_PRINTF(fmt,args...) +#define USB_PRINTF(fmt, args...) #endif
#define USB_BUFSIZ 512 @@ -88,7 +88,7 @@ void usb_hub_reset(void);
void __inline__ wait_ms(unsigned long ms) { - while(ms-->0) + while (ms-- > 0) udelay(1000); } /*************************************************************************** @@ -99,22 +99,22 @@ int usb_init(void) { int result;
- running=0; - dev_index=0; - asynch_allowed=1; + running = 0; + dev_index = 0; + asynch_allowed = 1; usb_hub_reset(); /* init low_level USB */ printf("USB: "); result = usb_lowlevel_init(); - /* if lowlevel init is OK, scan the bus for devices i.e. search HUBs and configure them */ - if(result==0) { + /* if lowlevel init is OK, scan the bus for devices + * i.e. search HUBs and configure them */ + if (result == 0) { printf("scanning bus for devices... "); - running=1; + running = 1; usb_scan_devices(); usb_started = 1; return 0; - } - else { + } else { printf("Error, couldn't init Lowlevel part\n"); usb_started = 0; return -1; @@ -143,7 +143,7 @@ int usb_stop(void) */ void usb_disable_asynch(int disable) { - asynch_allowed=!disable; + asynch_allowed = !disable; }
@@ -156,9 +156,9 @@ void usb_disable_asynch(int disable) * submits an Interrupt Message */ int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, - void *buffer,int transfer_len, int interval) + void *buffer, int transfer_len, int interval) { - return submit_int_msg(dev,pipe,buffer,transfer_len,interval); + return submit_int_msg(dev, pipe, buffer, transfer_len, interval); }
/* @@ -175,8 +175,10 @@ int usb_control_msg(struct usb_device *d unsigned short value, unsigned short index, void *data, unsigned short size, int timeout) { - if((timeout==0)&&(!asynch_allowed)) /* request for a asynch control pipe is not allowed */ + if ((timeout == 0) && (!asynch_allowed)) { + /* request for a asynch control pipe is not allowed */ return -1; + }
/* set setup command */ setup_packet.requesttype = requesttype; @@ -184,24 +186,24 @@ int usb_control_msg(struct usb_device *d setup_packet.value = cpu_to_le16(value); setup_packet.index = cpu_to_le16(index); setup_packet.length = cpu_to_le16(size); - USB_PRINTF("usb_control_msg: request: 0x%X, requesttype: 0x%X, value 0x%X index 0x%X length 0x%X\n", - request,requesttype,value,index,size); - dev->status=USB_ST_NOT_PROC; /*not yet processed */ + USB_PRINTF("usb_control_msg: request: 0x%X, requesttype: 0x%X, " \ + "value 0x%X index 0x%X length 0x%X\n", + request, requesttype, value, index, size); + dev->status = USB_ST_NOT_PROC; /*not yet processed */
- submit_control_msg(dev,pipe,data,size,&setup_packet); - if(timeout==0) { + submit_control_msg(dev, pipe, data, size, &setup_packet); + if (timeout == 0) return (int)size; - } - while(timeout--) { - if(!((volatile unsigned long)dev->status & USB_ST_NOT_PROC)) + + while (timeout--) { + if (!((volatile unsigned long)dev->status & USB_ST_NOT_PROC)) break; wait_ms(1); } - if(dev->status==0) + if (dev->status == 0) return dev->act_len; - else { + else return -1; - } }
/*------------------------------------------------------------------- @@ -214,15 +216,15 @@ int usb_bulk_msg(struct usb_device *dev, { if (len < 0) return -1; - dev->status=USB_ST_NOT_PROC; /*not yet processed */ - submit_bulk_msg(dev,pipe,data,len); - while(timeout--) { - if(!((volatile unsigned long)dev->status & USB_ST_NOT_PROC)) + dev->status = USB_ST_NOT_PROC; /*not yet processed */ + submit_bulk_msg(dev, pipe, data, len); + while (timeout--) { + if (!((volatile unsigned long)dev->status & USB_ST_NOT_PROC)) break; wait_ms(1); } - *actual_length=dev->act_len; - if(dev->status==0) + *actual_length = dev->act_len; + if (dev->status == 0) return 0; else return -1; @@ -237,9 +239,10 @@ int usb_bulk_msg(struct usb_device *dev, * returns the max packet size, depending on the pipe direction and * the configurations values */ -int usb_maxpacket(struct usb_device *dev,unsigned long pipe) +int usb_maxpacket(struct usb_device *dev, unsigned long pipe) { - if((pipe & USB_DIR_IN)==0) /* direction is out -> use emaxpacket out */ + /* direction is out -> use emaxpacket out */ + if ((pipe & USB_DIR_IN) == 0) return(dev->epmaxpacketout[((pipe>>15) & 0xf)]); else return(dev->epmaxpacketin[((pipe>>15) & 0xf)]); @@ -318,8 +321,9 @@ int usb_parse_config(struct usb_device *
dev->configno = cfgno; head = (struct usb_descriptor_header *) &buffer[0]; - if(head->bDescriptorType != USB_DT_CONFIG) { - printf(" ERROR: NOT USB_CONFIG_DESC %x\n", head->bDescriptorType); + if (head->bDescriptorType != USB_DT_CONFIG) { + printf(" ERROR: NOT USB_CONFIG_DESC %x\n", + head->bDescriptorType); return -1; } memcpy(&dev->config, buffer, buffer[0]); @@ -327,45 +331,52 @@ int usb_parse_config(struct usb_device * dev->config.no_of_if = 0;
index = dev->config.bLength; - /* Ok the first entry must be a configuration entry, now process the others */ + /* Ok the first entry must be a configuration entry, + * now process the others */ head = (struct usb_descriptor_header *) &buffer[index]; - while(index + 1 < dev->config.wTotalLength) { - switch(head->bDescriptorType) { - case USB_DT_INTERFACE: - if(((struct usb_interface_descriptor *) &buffer[index])-> - bInterfaceNumber != curr_if_num) { - /* this is a new interface, copy new desc */ - ifno = dev->config.no_of_if; - dev->config.no_of_if++; - memcpy(&dev->config.if_desc[ifno], - &buffer[index], buffer[index]); - dev->config.if_desc[ifno].no_of_ep = 0; - dev->config.if_desc[ifno].num_altsetting = 1; - curr_if_num = dev->config.if_desc[ifno].bInterfaceNumber; - } else { - /* found alternate setting for the interface */ - dev->config.if_desc[ifno].num_altsetting++; - } - break; - case USB_DT_ENDPOINT: - epno = dev->config.if_desc[ifno].no_of_ep; - dev->config.if_desc[ifno].no_of_ep++; /* found an endpoint */ - memcpy(&dev->config.if_desc[ifno].ep_desc[epno], + while (index + 1 < dev->config.wTotalLength) { + switch (head->bDescriptorType) { + case USB_DT_INTERFACE: + if (((struct usb_interface_descriptor *) \ + &buffer[index])->bInterfaceNumber != curr_if_num) { + /* this is a new interface, copy new desc */ + ifno = dev->config.no_of_if; + dev->config.no_of_if++; + memcpy(&dev->config.if_desc[ifno], &buffer[index], buffer[index]); - le16_to_cpus(&(dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize)); - USB_PRINTF("if %d, ep %d\n", ifno, epno); - break; - default: - if(head->bLength == 0) - return 1; - USB_PRINTF("unknown Description Type : %x\n", head->bDescriptorType); - { - ch = (unsigned char *)head; - for(i = 0; i < head->bLength; i++) - USB_PRINTF("%02X ", *ch++); - USB_PRINTF("\n\n\n"); - } - break; + dev->config.if_desc[ifno].no_of_ep = 0; + dev->config.if_desc[ifno].num_altsetting = 1; + curr_if_num = + dev->config.if_desc[ifno].bInterfaceNumber; + } else { + /* found alternate setting for the interface */ + dev->config.if_desc[ifno].num_altsetting++; + } + break; + case USB_DT_ENDPOINT: + epno = dev->config.if_desc[ifno].no_of_ep; + /* found an endpoint */ + dev->config.if_desc[ifno].no_of_ep++; + memcpy(&dev->config.if_desc[ifno].ep_desc[epno], + &buffer[index], buffer[index]); + le16_to_cpus(&(dev->config.if_desc[ifno].ep_desc[epno].\ + wMaxPacketSize)); + USB_PRINTF("if %d, ep %d\n", ifno, epno); + break; + default: + if (head->bLength == 0) + return 1; + + USB_PRINTF("unknown Description Type : %x\n", + head->bDescriptorType); + + { + ch = (unsigned char *)head; + for (i = 0; i < head->bLength; i++) + USB_PRINTF("%02X ", *ch++); + USB_PRINTF("\n\n\n"); + } + break; } index += head->bLength; head = (struct usb_descriptor_header *)&buffer[index]; @@ -384,7 +395,8 @@ int usb_clear_halt(struct usb_device *de int endp = usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, USB_CNTL_TIMEOUT * 3); + USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, + endp, NULL, 0, USB_CNTL_TIMEOUT * 3);
/* don't clear if failed */ if (result < 0) @@ -406,7 +418,8 @@ int usb_clear_halt(struct usb_device *de /********************************************************************** * get_descriptor type */ -int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size) +int usb_get_descriptor(struct usb_device *dev, unsigned char type, + unsigned char index, void *buf, int size) { int res; res = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), @@ -419,32 +432,36 @@ int usb_get_descriptor(struct usb_device /********************************************************************** * gets configuration cfgno and store it in the buffer */ -int usb_get_configuration_no(struct usb_device *dev,unsigned char *buffer,int cfgno) +int usb_get_configuration_no(struct usb_device *dev, + unsigned char *buffer, int cfgno) { int result; unsigned int tmp; struct usb_config_descriptor *config;
- config=(struct usb_config_descriptor *)&buffer[0]; + config = (struct usb_config_descriptor *)&buffer[0]; result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8); if (result < 8) { if (result < 0) - printf("unable to get descriptor, error %lX\n",dev->status); + printf("unable to get descriptor, error %lX\n", + dev->status); else - printf("config descriptor too short (expected %i, got %i)\n",8,result); + printf("config descriptor too short " \ + "(expected %i, got %i)\n", 8, result); return -1; } tmp = le16_to_cpu(config->wTotalLength);
if (tmp > USB_BUFSIZ) { - USB_PRINTF("usb_get_configuration_no: failed to get descriptor - too long: %d\n", - tmp); + USB_PRINTF("usb_get_configuration_no: failed to get " \ + "descriptor - too long: %d\n", tmp); return -1; }
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, tmp); - USB_PRINTF("get_conf_no %d Result %d, wLength %d\n",cfgno,result,tmp); + USB_PRINTF("get_conf_no %d Result %d, wLength %d\n", + cfgno, result, tmp); return result; }
@@ -456,11 +473,11 @@ int usb_set_address(struct usb_device *d { int res;
- USB_PRINTF("set address %d\n",dev->devnum); - res=usb_control_msg(dev, usb_snddefctrl(dev), - USB_REQ_SET_ADDRESS, 0, - (dev->devnum),0, - NULL,0, USB_CNTL_TIMEOUT); + USB_PRINTF("set address %d\n", dev->devnum); + res = usb_control_msg(dev, usb_snddefctrl(dev), + USB_REQ_SET_ADDRESS, 0, + (dev->devnum), 0, + NULL, 0, USB_CNTL_TIMEOUT); return res; }
@@ -484,16 +501,19 @@ int usb_set_interface(struct usb_device } /* * We should return now for devices with only one alternate setting. - * According to 9.4.10 of the Universal Serial Bus Specification Revision 2.0 - * such devices can return with a STALL. This results in some USB sticks - * timeouting during initialization and then being unusable in U-Boot. + * According to 9.4.10 of the Universal Serial Bus Specification + * Revision 2.0 such devices can return with a STALL. This results in + * some USB sticks timeouting during initialization and then being + * unusable in U-Boot. */ if (if_face->num_altsetting == 1) return 0;
- if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate, - interface, NULL, 0, USB_CNTL_TIMEOUT * 5)) < 0) + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, + alternate, interface, NULL, 0, + USB_CNTL_TIMEOUT * 5); + if (ret < 0) return ret;
return 0; @@ -505,18 +525,17 @@ int usb_set_interface(struct usb_device int usb_set_configuration(struct usb_device *dev, int configuration) { int res; - USB_PRINTF("set configuration %d\n",configuration); + USB_PRINTF("set configuration %d\n", configuration); /* set setup command */ - res=usb_control_msg(dev, usb_sndctrlpipe(dev,0), - USB_REQ_SET_CONFIGURATION, 0, - configuration,0, - NULL,0, USB_CNTL_TIMEOUT); - if(res==0) { + res = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_CONFIGURATION, 0, + configuration, 0, + NULL, 0, USB_CNTL_TIMEOUT); + if (res == 0) { dev->toggle[0] = 0; dev->toggle[1] = 0; return 0; - } - else + } else return -1; }
@@ -543,11 +562,13 @@ int usb_set_idle(struct usb_device *dev, /******************************************************************** * get report */ -int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size) +int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, + unsigned char id, void *buf, int size) { return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - (type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT); + USB_REQ_GET_REPORT, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + (type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT); }
/******************************************************************** @@ -564,7 +585,8 @@ int usb_get_class_descriptor(struct usb_ /******************************************************************** * get string index in buffer */ -int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size) +int usb_get_string(struct usb_device *dev, unsigned short langid, + unsigned char index, void *buf, int size) { int i; int result; @@ -655,17 +677,19 @@ int usb_string(struct usb_device *dev, i if (!dev->have_langid) { err = usb_string_sub(dev, 0, 0, tbuf); if (err < 0) { - USB_PRINTF("error getting string descriptor 0 (error=%x)\n",dev->status); + USB_PRINTF("error getting string descriptor 0 " \ + "(error=%x)\n", dev->status); return -1; } else if (tbuf[0] < 4) { USB_PRINTF("string descriptor 0 too short\n"); return -1; } else { dev->have_langid = -1; - dev->string_langid = tbuf[2] | (tbuf[3]<< 8); + dev->string_langid = tbuf[2] | (tbuf[3] << 8); /* always use the first langid listed */ - USB_PRINTF("USB device number %d default language ID 0x%x\n", - dev->devnum, dev->string_langid); + USB_PRINTF("USB device number %d default " \ + "language ID 0x%x\n", + dev->devnum, dev->string_langid); } }
@@ -697,9 +721,9 @@ int usb_string(struct usb_device *dev, i /* returns a pointer to the device with the index [index]. * if the device is not assigned (dev->devnum==-1) returns NULL */ -struct usb_device * usb_get_dev_index(int index) +struct usb_device *usb_get_dev_index(int index) { - if(usb_dev[index].devnum==-1) + if (usb_dev[index].devnum == -1) return NULL; else return &usb_dev[index]; @@ -709,21 +733,22 @@ struct usb_device * usb_get_dev_index(in /* returns a pointer of a new device structure or NULL, if * no device struct is available */ -struct usb_device * usb_alloc_new_device(void) +struct usb_device *usb_alloc_new_device(void) { int i; - USB_PRINTF("New Device %d\n",dev_index); - if(dev_index==USB_MAX_DEVICE) { - printf("ERROR, too many USB Devices, max=%d\n",USB_MAX_DEVICE); + USB_PRINTF("New Device %d\n", dev_index); + if (dev_index == USB_MAX_DEVICE) { + printf("ERROR, too many USB Devices, max=%d\n", USB_MAX_DEVICE); return NULL; } - usb_dev[dev_index].devnum=dev_index+1; /* default Address is 0, real addresses start with 1 */ - usb_dev[dev_index].maxchild=0; - for(i=0;i<USB_MAXCHILDREN;i++) - usb_dev[dev_index].children[i]=NULL; - usb_dev[dev_index].parent=NULL; + /* default Address is 0, real addresses start with 1 */ + usb_dev[dev_index].devnum = dev_index + 1; + usb_dev[dev_index].maxchild = 0; + for (i = 0; i < USB_MAXCHILDREN; i++) + usb_dev[dev_index].children[i] = NULL; + usb_dev[dev_index].parent = NULL; dev_index++; - return &usb_dev[dev_index-1]; + return &usb_dev[dev_index - 1]; }
@@ -788,7 +813,7 @@ int usb_new_device(struct usb_device *de } } if (port < 0) { - printf("usb_new_device: cannot locate device's port..\n"); + printf("usb_new_device:cannot locate device's port.\n"); return 1; }
@@ -803,7 +828,8 @@ int usb_new_device(struct usb_device *de /* and this is the old and known way of initializing devices */ err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); if (err < 8) { - printf("\n USB device not responding, giving up (status=%lX)\n",dev->status); + printf("\n USB device not responding, " \ + "giving up (status=%lX)\n", dev->status); return 1; } #endif @@ -811,17 +837,18 @@ int usb_new_device(struct usb_device *de dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; switch (dev->descriptor.bMaxPacketSize0) { - case 8: dev->maxpacketsize = 0; break; - case 16: dev->maxpacketsize = 1; break; - case 32: dev->maxpacketsize = 2; break; - case 64: dev->maxpacketsize = 3; break; + case 8: dev->maxpacketsize = 0; break; + case 16: dev->maxpacketsize = 1; break; + case 32: dev->maxpacketsize = 2; break; + case 64: dev->maxpacketsize = 3; break; } dev->devnum = addr;
err = usb_set_address(dev); /* set address */
if (err < 0) { - printf("\n USB device not accepting new address (error=%lX)\n", dev->status); + printf("\n USB device not accepting new address " \ + "(error=%lX)\n", dev->status); return 1; }
@@ -829,12 +856,15 @@ int usb_new_device(struct usb_device *de
tmp = sizeof(dev->descriptor);
- err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor)); + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, + &dev->descriptor, sizeof(dev->descriptor)); if (err < tmp) { if (err < 0) - printf("unable to get device descriptor (error=%d)\n",err); + printf("unable to get device descriptor (error=%d)\n", + err); else - printf("USB device descriptor short read (expected %i, got %i)\n",tmp,err); + printf("USB device descriptor short read " \ + "(expected %i, got %i)\n", tmp, err); return 1; } /* correct le values */ @@ -843,30 +873,35 @@ int usb_new_device(struct usb_device *de le16_to_cpus(&dev->descriptor.idProduct); le16_to_cpus(&dev->descriptor.bcdDevice); /* only support for one config for now */ - usb_get_configuration_no(dev,&tmpbuf[0],0); - usb_parse_config(dev,&tmpbuf[0],0); + usb_get_configuration_no(dev, &tmpbuf[0], 0); + usb_parse_config(dev, &tmpbuf[0], 0); usb_set_maxpacket(dev); /* we set the default configuration here */ if (usb_set_configuration(dev, dev->config.bConfigurationValue)) { - printf("failed to set default configuration len %d, status %lX\n",dev->act_len,dev->status); + printf("failed to set default configuration " \ + "len %d, status %lX\n", dev->act_len, dev->status); return -1; } USB_PRINTF("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n", - dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber); + dev->descriptor.iManufacturer, dev->descriptor.iProduct, + dev->descriptor.iSerialNumber); memset(dev->mf, 0, sizeof(dev->mf)); memset(dev->prod, 0, sizeof(dev->prod)); memset(dev->serial, 0, sizeof(dev->serial)); if (dev->descriptor.iManufacturer) - usb_string(dev, dev->descriptor.iManufacturer, dev->mf, sizeof(dev->mf)); + usb_string(dev, dev->descriptor.iManufacturer, + dev->mf, sizeof(dev->mf)); if (dev->descriptor.iProduct) - usb_string(dev, dev->descriptor.iProduct, dev->prod, sizeof(dev->prod)); + usb_string(dev, dev->descriptor.iProduct, + dev->prod, sizeof(dev->prod)); if (dev->descriptor.iSerialNumber) - usb_string(dev, dev->descriptor.iSerialNumber, dev->serial, sizeof(dev->serial)); + usb_string(dev, dev->descriptor.iSerialNumber, + dev->serial, sizeof(dev->serial)); USB_PRINTF("Manufacturer %s\n", dev->mf); USB_PRINTF("Product %s\n", dev->prod); USB_PRINTF("SerialNumber %s\n", dev->serial); /* now prode if the device is a hub */ - usb_hub_probe(dev,0); + usb_hub_probe(dev, 0); return 0; }
@@ -877,15 +912,15 @@ void usb_scan_devices(void) struct usb_device *dev;
/* first make all devices unknown */ - for(i=0;i<USB_MAX_DEVICE;i++) { - memset(&usb_dev[i],0,sizeof(struct usb_device)); + for (i = 0; i < USB_MAX_DEVICE; i++) { + memset(&usb_dev[i], 0, sizeof(struct usb_device)); usb_dev[i].devnum = -1; } - dev_index=0; + dev_index = 0; /* device 0 is always present (root hub, so let it analyze) */ - dev=usb_alloc_new_device(); + dev = usb_alloc_new_device(); usb_new_device(dev); - printf("%d USB Device(s) found\n",dev_index); + printf("%d USB Device(s) found\n", dev_index); /* insert "driver" if possible */ #ifdef CONFIG_USB_KEYBOARD drv_usb_kbd_init(); @@ -902,9 +937,9 @@ void usb_scan_devices(void) #undef USB_HUB_DEBUG
#ifdef USB_HUB_DEBUG -#define USB_HUB_PRINTF(fmt,args...) printf (fmt ,##args) +#define USB_HUB_PRINTF(fmt, args...) printf (fmt , ##args) #else -#define USB_HUB_PRINTF(fmt,args...) +#define USB_HUB_PRINTF(fmt, args...) #endif
@@ -922,19 +957,22 @@ int usb_get_hub_descriptor(struct usb_de int usb_clear_hub_feature(struct usb_device *dev, int feature) { return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, USB_CNTL_TIMEOUT); + USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, + 0, NULL, 0, USB_CNTL_TIMEOUT); }
int usb_clear_port_feature(struct usb_device *dev, int port, int feature) { return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0, USB_CNTL_TIMEOUT); + USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, + port, NULL, 0, USB_CNTL_TIMEOUT); }
int usb_set_port_feature(struct usb_device *dev, int port, int feature) { return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0, USB_CNTL_TIMEOUT); + USB_REQ_SET_FEATURE, USB_RT_PORT, feature, + port, NULL, 0, USB_CNTL_TIMEOUT); }
int usb_get_hub_status(struct usb_device *dev, void *data) @@ -957,27 +995,27 @@ static void usb_hub_power_on(struct usb_ int i; struct usb_device *dev;
- dev=hub->pusb_dev; + dev = hub->pusb_dev; /* Enable power to the ports */ USB_HUB_PRINTF("enabling power on all ports\n"); for (i = 0; i < dev->maxchild; i++) { usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); - USB_HUB_PRINTF("port %d returns %lX\n",i+1,dev->status); + USB_HUB_PRINTF("port %d returns %lX\n", i + 1, dev->status); wait_ms(hub->desc.bPwrOn2PwrGood * 2); } }
void usb_hub_reset(void) { - usb_hub_index=0; + usb_hub_index = 0; }
struct usb_hub_device *usb_hub_allocate(void) { - if(usb_hub_index<USB_MAX_HUB) { + if (usb_hub_index < USB_MAX_HUB) return &hub_dev[usb_hub_index++]; - } - printf("ERROR: USB_MAX_HUB (%d) reached\n",USB_MAX_HUB); + + printf("ERROR: USB_MAX_HUB (%d) reached\n", USB_MAX_HUB); return NULL; }
@@ -990,39 +1028,42 @@ static int hub_port_reset(struct usb_dev struct usb_port_status portsts; unsigned short portstatus, portchange;
- USB_HUB_PRINTF("hub_port_reset: resetting port %d...\n", port); - for(tries=0;tries<MAX_TRIES;tries++) { + for (tries = 0; tries < MAX_TRIES; tries++) {
usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET); wait_ms(200);
- if (usb_get_port_status(dev, port + 1, &portsts)<0) { - USB_HUB_PRINTF("get_port_status failed status %lX\n",dev->status); + if (usb_get_port_status(dev, port + 1, &portsts) < 0) { + USB_HUB_PRINTF("get_port_status failed status %lX\n", + dev->status); return -1; } portstatus = le16_to_cpu(portsts.wPortStatus); portchange = le16_to_cpu(portsts.wPortChange); - USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus ,portchange, - portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed"); - USB_HUB_PRINTF("STAT_C_CONNECTION = %d STAT_CONNECTION = %d USB_PORT_STAT_ENABLE %d\n", + USB_HUB_PRINTF("portstatus %x, change %x, %s\n", + portstatus, portchange, + portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? \ + "Low Speed" : "High Speed"); + USB_HUB_PRINTF("STAT_C_CONNECTION = %d STAT_CONNECTION = %d" \ + " USB_PORT_STAT_ENABLE %d\n", (portchange & USB_PORT_STAT_C_CONNECTION) ? 1 : 0, (portstatus & USB_PORT_STAT_CONNECTION) ? 1 : 0, (portstatus & USB_PORT_STAT_ENABLE) ? 1 : 0); + if ((portchange & USB_PORT_STAT_C_CONNECTION) || !(portstatus & USB_PORT_STAT_CONNECTION)) return -1;
- if (portstatus & USB_PORT_STAT_ENABLE) { - + if (portstatus & USB_PORT_STAT_ENABLE) break; - }
wait_ms(200); }
- if (tries==MAX_TRIES) { - USB_HUB_PRINTF("Cannot enable port %i after %i retries, disabling port.\n", port+1, MAX_TRIES); + if (tries == MAX_TRIES) { + USB_HUB_PRINTF("Cannot enable port %i after %i retries, " \ + "disabling port.\n", port + 1, MAX_TRIES); USB_HUB_PRINTF("Maybe the USB cable is bad?\n"); return -1; } @@ -1030,7 +1071,6 @@ static int hub_port_reset(struct usb_dev usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_RESET); *portstat = portstatus; return 0; - }
@@ -1041,22 +1081,24 @@ void usb_hub_port_connect_change(struct unsigned short portstatus, portchange;
/* Check status */ - if (usb_get_port_status(dev, port + 1, &portsts)<0) { + if (usb_get_port_status(dev, port + 1, &portsts) < 0) { USB_HUB_PRINTF("get_port_status failed\n"); return; }
portstatus = le16_to_cpu(portsts.wPortStatus); portchange = le16_to_cpu(portsts.wPortChange); - USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus, portchange, - portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed"); + USB_HUB_PRINTF("portstatus %x, change %x, %s\n", + portstatus, portchange, + portstatus&(1 << USB_PORT_FEAT_LOWSPEED) ? \ + "Low Speed" : "High Speed");
/* Clear the connection change status */ usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION);
/* Disconnect any existing devices under this port */ if (((!(portstatus & USB_PORT_STAT_CONNECTION)) && - (!(portstatus & USB_PORT_STAT_ENABLE)))|| (dev->children[port])) { + (!(portstatus & USB_PORT_STAT_ENABLE))) || (dev->children[port])) { USB_HUB_PRINTF("usb_disconnect(&hub->children[port]);\n"); /* Return now if nothing is connected */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) @@ -1073,11 +1115,11 @@ void usb_hub_port_connect_change(struct wait_ms(200);
/* Allocate a new device struct for it */ - usb=usb_alloc_new_device(); + usb = usb_alloc_new_device(); usb->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0;
dev->children[port] = usb; - usb->parent=dev; + usb->parent = dev; /* Run it through the hoops (find a driver, etc) */ if (usb_new_device(usb)) { /* Woops, disable the port */ @@ -1096,13 +1138,14 @@ int usb_hub_configure(struct usb_device struct usb_hub_device *hub;
/* "allocate" Hub device */ - hub=usb_hub_allocate(); - if(hub==NULL) + hub = usb_hub_allocate(); + if (hub == NULL) return -1; - hub->pusb_dev=dev; + hub->pusb_dev = dev; /* Get the the hub descriptor */ if (usb_get_hub_descriptor(dev, buffer, 4) < 0) { - USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor, giving up %lX\n",dev->status); + USB_HUB_PRINTF("usb_hub_configure: failed to get hub " \ + "descriptor, giving up %lX\n", dev->status); return -1; } descriptor = (struct usb_hub_descriptor *)buffer; @@ -1110,43 +1153,48 @@ int usb_hub_configure(struct usb_device /* silence compiler warning if USB_BUFSIZ is > 256 [= sizeof(char)] */ i = descriptor->bLength; if (i > USB_BUFSIZ) { - USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor - too long: %d\n", - descriptor->bLength); + USB_HUB_PRINTF("usb_hub_configure: failed to get hub " \ + "descriptor - too long: %d\n", + descriptor->bLength); return -1; }
if (usb_get_hub_descriptor(dev, buffer, descriptor->bLength) < 0) { - USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor 2nd giving up %lX\n",dev->status); + USB_HUB_PRINTF("usb_hub_configure: failed to get hub " \ + "descriptor 2nd giving up %lX\n", dev->status); return -1; } - memcpy((unsigned char *)&hub->desc,buffer,descriptor->bLength); + memcpy((unsigned char *)&hub->desc, buffer, descriptor->bLength); /* adjust 16bit values */ - hub->desc.wHubCharacteristics = le16_to_cpu(descriptor->wHubCharacteristics); + hub->desc.wHubCharacteristics = + le16_to_cpu(descriptor->wHubCharacteristics); /* set the bitmap */ - bitmap=(unsigned char *)&hub->desc.DeviceRemovable[0]; - memset(bitmap,0xff,(USB_MAXCHILDREN+1+7)/8); /* devices not removable by default */ - bitmap=(unsigned char *)&hub->desc.PortPowerCtrlMask[0]; - memset(bitmap,0xff,(USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */ - for(i=0;i<((hub->desc.bNbrPorts + 1 + 7)/8);i++) { - hub->desc.DeviceRemovable[i]=descriptor->DeviceRemovable[i]; - } - for(i=0;i<((hub->desc.bNbrPorts + 1 + 7)/8);i++) { - hub->desc.DeviceRemovable[i]=descriptor->PortPowerCtrlMask[i]; - } + bitmap = (unsigned char *)&hub->desc.DeviceRemovable[0]; + /* devices not removable by default */ + memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8); + bitmap = (unsigned char *)&hub->desc.PortPowerCtrlMask[0]; + memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */ + + for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++) + hub->desc.DeviceRemovable[i] = descriptor->DeviceRemovable[i]; + + for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++) + hub->desc.DeviceRemovable[i] = descriptor->PortPowerCtrlMask[i]; + dev->maxchild = descriptor->bNbrPorts; USB_HUB_PRINTF("%d ports detected\n", dev->maxchild);
switch (hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) { - case 0x00: - USB_HUB_PRINTF("ganged power switching\n"); - break; - case 0x01: - USB_HUB_PRINTF("individual port power switching\n"); - break; - case 0x02: - case 0x03: - USB_HUB_PRINTF("unknown reserved power switching mode\n"); - break; + case 0x00: + USB_HUB_PRINTF("ganged power switching\n"); + break; + case 0x01: + USB_HUB_PRINTF("individual port power switching\n"); + break; + case 0x02: + case 0x03: + USB_HUB_PRINTF("unknown reserved power switching mode\n"); + break; }
if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND) @@ -1155,40 +1203,52 @@ int usb_hub_configure(struct usb_device USB_HUB_PRINTF("standalone hub\n");
switch (hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) { - case 0x00: - USB_HUB_PRINTF("global over-current protection\n"); - break; - case 0x08: - USB_HUB_PRINTF("individual port over-current protection\n"); - break; - case 0x10: - case 0x18: - USB_HUB_PRINTF("no over-current protection\n"); - break; - } - USB_HUB_PRINTF("power on to power good time: %dms\n", descriptor->bPwrOn2PwrGood * 2); - USB_HUB_PRINTF("hub controller current requirement: %dmA\n", descriptor->bHubContrCurrent); + case 0x00: + USB_HUB_PRINTF("global over-current protection\n"); + break; + case 0x08: + USB_HUB_PRINTF("individual port over-current protection\n"); + break; + case 0x10: + case 0x18: + USB_HUB_PRINTF("no over-current protection\n"); + break; + } + + USB_HUB_PRINTF("power on to power good time: %dms\n", + descriptor->bPwrOn2PwrGood * 2); + USB_HUB_PRINTF("hub controller current requirement: %dmA\n", + descriptor->bHubContrCurrent); + for (i = 0; i < dev->maxchild; i++) USB_HUB_PRINTF("port %d is%s removable\n", i + 1, - hub->desc.DeviceRemovable[(i + 1)/8] & (1 << ((i + 1)%8)) ? " not" : ""); + hub->desc.DeviceRemovable[(i + 1) / 8] & \ + (1 << ((i + 1) % 8)) ? " not" : ""); + if (sizeof(struct usb_hub_status) > USB_BUFSIZ) { - USB_HUB_PRINTF("usb_hub_configure: failed to get Status - too long: %d\n", - descriptor->bLength); + USB_HUB_PRINTF("usb_hub_configure: failed to get Status - " \ + "too long: %d\n", descriptor->bLength); return -1; }
if (usb_get_hub_status(dev, buffer) < 0) { - USB_HUB_PRINTF("usb_hub_configure: failed to get Status %lX\n",dev->status); + USB_HUB_PRINTF("usb_hub_configure: failed to get Status %lX\n", + dev->status); return -1; } + hubsts = (struct usb_hub_status *)buffer; USB_HUB_PRINTF("get_hub_status returned status %X, change %X\n", - le16_to_cpu(hubsts->wHubStatus),le16_to_cpu(hubsts->wHubChange)); + le16_to_cpu(hubsts->wHubStatus), + le16_to_cpu(hubsts->wHubChange)); USB_HUB_PRINTF("local power source is %s\n", - (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good"); + (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? \ + "lost (inactive)" : "good"); USB_HUB_PRINTF("%sover-current condition exists\n", - (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? "" : "no "); + (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? \ + "" : "no "); usb_hub_power_on(hub); + for (i = 0; i < dev->maxchild; i++) { struct usb_port_status portsts; unsigned short portstatus, portchange; @@ -1197,41 +1257,51 @@ int usb_hub_configure(struct usb_device USB_HUB_PRINTF("get_port_status failed\n"); continue; } + portstatus = le16_to_cpu(portsts.wPortStatus); portchange = le16_to_cpu(portsts.wPortChange); - USB_HUB_PRINTF("Port %d Status %X Change %X\n",i+1,portstatus,portchange); + USB_HUB_PRINTF("Port %d Status %X Change %X\n", + i + 1, portstatus, portchange); + if (portchange & USB_PORT_STAT_C_CONNECTION) { USB_HUB_PRINTF("port %d connection change\n", i + 1); usb_hub_port_connect_change(dev, i); } if (portchange & USB_PORT_STAT_C_ENABLE) { - USB_HUB_PRINTF("port %d enable change, status %x\n", i + 1, portstatus); - usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE); - - /* EM interference sometimes causes bad shielded USB devices to - * be shutdown by the hub, this hack enables them again. - * Works at least with mouse driver */ + USB_HUB_PRINTF("port %d enable change, status %x\n", + i + 1, portstatus); + usb_clear_port_feature(dev, i + 1, + USB_PORT_FEAT_C_ENABLE); + + /* EM interference sometimes causes bad shielded USB + * devices to be shutdown by the hub, this hack enables + * them again. Works at least with mouse driver */ if (!(portstatus & USB_PORT_STAT_ENABLE) && - (portstatus & USB_PORT_STAT_CONNECTION) && (dev->children[i])) { - USB_HUB_PRINTF("already running port %i disabled by hub (EMI?), re-enabling...\n", - i + 1); + (portstatus & USB_PORT_STAT_CONNECTION) && + ((dev->children[i]))) { + USB_HUB_PRINTF("already running port %i " \ + "disabled by hub (EMI?), " \ + "re-enabling...\n", i + 1); usb_hub_port_connect_change(dev, i); } } if (portstatus & USB_PORT_STAT_SUSPEND) { USB_HUB_PRINTF("port %d suspend change\n", i + 1); - usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_SUSPEND); + usb_clear_port_feature(dev, i + 1, + USB_PORT_FEAT_SUSPEND); }
if (portchange & USB_PORT_STAT_C_OVERCURRENT) { USB_HUB_PRINTF("port %d over-current change\n", i + 1); - usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT); + usb_clear_port_feature(dev, i + 1, + USB_PORT_FEAT_C_OVER_CURRENT); usb_hub_power_on(hub); }
if (portchange & USB_PORT_STAT_C_RESET) { USB_HUB_PRINTF("port %d reset change\n", i + 1); - usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET); + usb_clear_port_feature(dev, i + 1, + USB_PORT_FEAT_C_RESET); } } /* end for i all ports */
@@ -1265,7 +1335,7 @@ int usb_hub_probe(struct usb_device *dev return 0; /* We found a hub */ USB_HUB_PRINTF("USB hub found\n"); - ret=usb_hub_configure(dev); + ret = usb_hub_configure(dev); return ret; }
Index: u-boot/drivers/usb/usb_ohci.c =================================================================== --- u-boot.orig/drivers/usb/usb_ohci.c 2008-09-16 14:32:13.000000000 +0200 +++ u-boot/drivers/usb/usb_ohci.c 2008-09-16 14:44:59.000000000 +0200 @@ -97,7 +97,8 @@ # define writel(a, b) (*((volatile u32 *)(b)) = ((volatile u32)a)) #endif /* CFG_OHCI_SWAP_REG_ACCESS */
-#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) +#define min_t(type, x, y) \ + ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
#ifdef CONFIG_PCI_OHCI static struct pci_device_id ohci_pci_ids[] = { @@ -120,13 +121,13 @@ static struct pci_device_id ehci_pci_ids #ifdef DEBUG #define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg) #else -#define dbg(format, arg...) do {} while(0) +#define dbg(format, arg...) do {} while (0) #endif /* DEBUG */ #define err(format, arg...) printf("ERROR: " format "\n", ## arg) #ifdef SHOW_INFO #define info(format, arg...) printf("INFO: " format "\n", ## arg) #else -#define info(format, arg...) do {} while(0) +#define info(format, arg...) do {} while (0) #endif
#ifdef CFG_OHCI_BE_CONTROLLER @@ -145,25 +146,24 @@ struct ohci_hcca ghcca[1]; struct ohci_hcca *phcca; /* this allocates EDs for all possible endpoints */ struct ohci_device ohci_dev; -/* RHSC flag */ -int got_rhsc; /* device which was disconnected */ struct usb_device *devgone;
-static inline u32 roothub_a (struct ohci *hc) - { return readl (&hc->regs->roothub.a); } -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 inline u32 roothub_portstatus (struct ohci *hc, int i) - { return readl (&hc->regs->roothub.portstatus[i]); } +static inline u32 roothub_a(struct ohci *hc) + { return readl(&hc->regs->roothub.a); } +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 inline u32 roothub_portstatus(struct ohci *hc, int i) + { return readl(&hc->regs->roothub.portstatus[i]); }
/* forward declaration */ -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); +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);
/*-------------------------------------------------------------------------* * URB support functions @@ -171,11 +171,11 @@ td_submit_job (struct usb_device * dev,
/* 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; + struct td *td;
last = urb->length - 1; if (last >= 0) { @@ -193,72 +193,74 @@ static void urb_free_priv (urb_priv_t * /*-------------------------------------------------------------------------*/
#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 (urb_priv_t *purb, struct usb_device * dev, - unsigned long pipe, void * buffer, - int transfer_len, struct devrequest * setup, char * str, int small) +static void pkt_print(urb_priv_t *purb, struct usb_device *dev, + unsigned long pipe, void *buffer, int transfer_len, + struct devrequest *setup, char *str, int small) { - dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx", + dbg("%s URB:[%4x] dev:%2lu,ep:%2lu-%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"), + 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 ? purb->actual_length : 0), transfer_len, dev->status); #ifdef OHCI_VERBOSE_DEBUG if (!small) { int i, len;
- if (usb_pipecontrol (pipe)) { - printf (__FILE__ ": cmd(8):"); + if (usb_pipecontrol(pipe)) { + printf(__FILE__ ": cmd(8):"); for (i = 0; i < 8 ; i++) - printf (" %02x", ((__u8 *) setup) [i]); - printf ("\n"); + printf(" %02x", ((__u8 *) setup) [i]); + printf("\n"); } if (transfer_len > 0 && buffer) { - printf (__FILE__ ": data(%d/%d):", + printf(__FILE__ ": data(%d/%d):", (purb ? purb->actual_length : 0), transfer_len); - len = usb_pipeout (pipe)? - transfer_len: + len = usb_pipeout(pipe)? transfer_len: (purb ? purb->actual_length : 0); 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) { +/* 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) +{ 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]); if (*ed_p == 0) continue; - printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i); + printf(__FILE__ ": %s branch int %2d(%2x):", str, i, i); while (*ed_p != 0 && j--) { ed_t *ed = (ed_t *)m32_swap(ed_p); - printf (" ed: %4x;", ed->hwINFO); + 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", + dbg("%s: 0x%08x%s%s%s%s%s%s%s%s%s", label, mask, (mask & OHCI_INTR_MIE) ? " MIE" : "", @@ -273,46 +275,46 @@ static void ohci_dump_intr_mask (char *l ); }
-static void maybe_print_eds (char *label, __u32 value) +static void maybe_print_eds(char *label, __u32 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;
- temp = readl (®s->revision) & 0xff; + temp = readl(®s->revision) & 0xff; if (temp != 0x10) - dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); + 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 = 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), + hcfs2string(temp & OHCI_CTRL_HCFS), (temp & OHCI_CTRL_BLE) ? " BLE" : "", (temp & OHCI_CTRL_CLE) ? " CLE" : "", (temp & OHCI_CTRL_IE) ? " IE" : "", @@ -320,8 +322,8 @@ static void ohci_dump_status (ohci_t *co temp & OHCI_CTRL_CBSR );
- temp = readl (®s->cmdstatus); - dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, + 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" : "", @@ -329,31 +331,31 @@ static void ohci_dump_status (ohci_t *co (temp & OHCI_HCR) ? " HCR" : "" );
- ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); - ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); + 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_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_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("ed_bulkhead", readl(®s->ed_bulkhead)); + maybe_print_eds("ed_bulkcurrent", readl(®s->ed_bulkcurrent));
- maybe_print_eds ("donehead", readl (®s->donehead)); + 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;
- temp = roothub_a (controller); + temp = roothub_a(controller); ndp = (temp & RH_A_NDP); #ifdef CONFIG_AT91C_PQFP_UHPBUG ndp = (ndp == 2) ? 1:0; #endif if (verbose) { - dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, + 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" : "", @@ -362,14 +364,14 @@ static void ohci_dump_roothub (ohci_t *c (temp & RH_A_PSM) ? " PSM" : "", ndp ); - temp = roothub_b (controller); - dbg ("roothub.b: %08x PPCM=%04x DR=%04x", + 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 = roothub_status(controller); + dbg("roothub.status: %08x%s%s%s%s%s%s", temp, (temp & RH_HS_CRWE) ? " CRWE" : "", (temp & RH_HS_OCIC) ? " OCIC" : "", @@ -381,8 +383,8 @@ static void ohci_dump_roothub (ohci_t *c }
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", + 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" : "", @@ -403,16 +405,16 @@ static void ohci_dump_roothub (ohci_t *c } }
-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 */
@@ -425,7 +427,7 @@ static void ohci_dump (ohci_t *controlle int sohci_submit_job(urb_priv_t *urb, struct devrequest *setup) { ohci_t *ohci; - ed_t * ed; + ed_t *ed; urb_priv_t *purb_priv = urb; int i, size = 0; struct usb_device *dev = urb->dev; @@ -443,27 +445,29 @@ int sohci_submit_job(urb_priv_t *urb, st return -1; }
- /* we're about to begin a new transaction here so mark the URB unfinished */ + /* 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, interval, 1))) { + ed = ep_add_ed(dev, pipe, interval, 1); + if (!ed) { 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; - case PIPE_INTERRUPT: /* 1 TD */ - size = 1; - 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; + case PIPE_INTERRUPT: /* 1 TD */ + size = 1; + break; }
ed->purb = urb; @@ -482,27 +486,28 @@ int sohci_submit_job(urb_priv_t *urb, st /* 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; } @@ -511,19 +516,19 @@ static inline int sohci_return_job(struc { struct ohci_regs *regs = hc->regs;
- switch (usb_pipetype (urb->pipe)) { + switch (usb_pipetype(urb->pipe)) { case PIPE_INTERRUPT: /* implicitly requeued */ if (urb->dev->irq_handle && (urb->dev->irq_act_len = urb->actual_length)) { - writel (OHCI_INTR_WDH, ®s->intrenable); - readl (®s->intrenable); /* PCI posting flush */ + writel(OHCI_INTR_WDH, ®s->intrenable); + readl(®s->intrenable); /* PCI posting flush */ urb->dev->irq_handle(urb->dev); - writel (OHCI_INTR_WDH, ®s->intrdisable); - readl (®s->intrdisable); /* PCI posting flush */ + writel(OHCI_INTR_WDH, ®s->intrdisable); + readl(®s->intrdisable); /* PCI posting flush */ } urb->actual_length = 0; - td_submit_job ( + td_submit_job( urb->dev, urb->pipe, urb->transfer_buffer, @@ -546,11 +551,11 @@ static inline int sohci_return_job(struc #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 m16_swap (ohci->hcca->frame_no); + return m16_swap(ohci->hcca->frame_no); } #endif
@@ -563,7 +568,7 @@ static int sohci_get_current_frame_numbe * returns the branch and * sets the interval to interval = 2^integer (ld (interval)) */
-static int ep_int_ballance (ohci_t * ohci, int interval, int load) +static int ep_int_ballance(ohci_t *ohci, int interval, int load) { int i, branch = 0;
@@ -585,20 +590,19 @@ static int ep_int_ballance (ohci_t * ohc
/* 2^int( ld (inter)) */
-static int ep_2_n_interval (int inter) +static int ep_2_n_interval(int inter) { int i; - for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++); + for (i = 0; ((inter >> i) > 1) && (i < 5); i++); return 1 << i; }
/*-------------------------------------------------------------------------*/
/* the int tree is a binary tree - * in order to process it sequentially the indexes of the branches have to be mapped - * the mapping reverses the bits of a word of num_bits length */ - -static int ep_rev (int num_bits, int word) + * in order to process it sequentially the indexes of the branches have to + * be mapped the mapping reverses the bits of a word of num_bits length */ +static int ep_rev(int num_bits, int word) { int i, wout = 0;
@@ -613,7 +617,7 @@ static int ep_rev (int num_bits, int wor
/* 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; int int_branch; @@ -621,7 +625,7 @@ static int ep_link (ohci_t *ohci, ed_t * int inter; int interval; int load; - __u32 * ed_p; + __u32 *ed_p;
ed->state = ED_OPER; ed->int_interval = 0; @@ -629,49 +633,54 @@ static int ep_link (ohci_t *ohci, ed_t * switch (ed->type) { case PIPE_CONTROL: ed->hwNextED = 0; - if (ohci->ed_controltail == NULL) { - writel (ed, &ohci->regs->ed_controlhead); - } else { - ohci->ed_controltail->hwNextED = m32_swap ((unsigned long)ed); - } + if (ohci->ed_controltail == NULL) + writel(ed, &ohci->regs->ed_controlhead); + else + ohci->ed_controltail->hwNextED = + m32_swap((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->hc_control |= OHCI_CTRL_CLE; - writel (ohci->hc_control, &ohci->regs->control); + writel(ohci->hc_control, &ohci->regs->control); } ohci->ed_controltail = edi; break;
case PIPE_BULK: ed->hwNextED = 0; - if (ohci->ed_bulktail == NULL) { - writel (ed, &ohci->regs->ed_bulkhead); - } else { - ohci->ed_bulktail->hwNextED = m32_swap ((unsigned long)ed); - } + if (ohci->ed_bulktail == NULL) + writel(ed, &ohci->regs->ed_bulkhead); + else + ohci->ed_bulktail->hwNextED = + m32_swap((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->hc_control |= OHCI_CTRL_BLE; - writel (ohci->hc_control, &ohci->regs->control); + writel(ohci->hc_control, &ohci->regs->control); } ohci->ed_bulktail = edi; break;
case PIPE_INTERRUPT: load = ed->int_load; - interval = ep_2_n_interval (ed->int_period); + interval = ep_2_n_interval(ed->int_period); ed->int_interval = interval; - int_branch = ep_int_ballance (ohci, interval, load); + int_branch = ep_int_ballance(ohci, interval, load); ed->int_branch = int_branch;
- for (i = 0; i < ep_rev (6, interval); i += inter) { + for (i = 0; i < ep_rev(6, interval); i += inter) { inter = 1; - for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i) + int_branch]); - (*ed_p != 0) && (((ed_t *)ed_p)->int_interval >= interval); + for (ed_p = &(ohci->hcca->int_table[\ + ep_rev(5, i) + int_branch]); + (*ed_p != 0) && + (((ed_t *)ed_p)->int_interval >= interval); ed_p = &(((ed_t *)ed_p)->hwNextED)) - inter = ep_rev (6, ((ed_t *)ed_p)->int_interval); + inter = ep_rev(6, + ((ed_t *)ed_p)->int_interval); ed->hwNextED = *ed_p; *ed_p = m32_swap((unsigned long)ed); } @@ -683,19 +692,21 @@ static int ep_link (ohci_t *ohci, ed_t * /*-------------------------------------------------------------------------*/
/* scan the periodic table to find and unlink this ED */ -static void periodic_unlink ( struct ohci *ohci, volatile struct ed *ed, - unsigned index, unsigned period) +static void periodic_unlink(struct ohci *ohci, volatile struct ed *ed, + unsigned index, unsigned period) { for (; index < NUM_INTS; index += period) { __u32 *ed_p = &ohci->hcca->int_table [index];
/* ED might have been unlinked through another path */ while (*ed_p != 0) { - if (((struct ed *)m32_swap ((unsigned long)ed_p)) == ed) { + if (((struct ed *) + m32_swap((unsigned long)ed_p)) == ed) { *ed_p = ed->hwNextED; break; } - ed_p = & (((struct ed *)m32_swap ((unsigned long)ed_p))->hwNextED); + ed_p = &(((struct ed *) + m32_swap((unsigned long)ed_p))->hwNextED); } } } @@ -705,28 +716,30 @@ static void periodic_unlink ( struct ohc * 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; int i;
- ed->hwINFO |= m32_swap (OHCI_ED_SKIP); + ed->hwINFO |= m32_swap(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 (m32_swap (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_controlhead); + writel(m32_swap(*((__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 *)m32_swap (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; + ((ed_t *)m32_swap( + *((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; } break;
@@ -734,21 +747,23 @@ static int ep_unlink (ohci_t *ohci, ed_t 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 (m32_swap (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_bulkhead); + writel(m32_swap(*((__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 *)m32_swap (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; + ((ed_t *)m32_swap( + *((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; } break;
case PIPE_INTERRUPT: - periodic_unlink (ohci, ed, 0, 1); + periodic_unlink(ohci, ed, 0, 1); for (i = ed->int_branch; i < 32; i += ed->int_interval) ohci->ohci_int_load[i] -= ed->int_load; break; @@ -767,15 +782,15 @@ static int ep_unlink (ohci_t *ohci, ed_t * 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, - int interval, int load) +static ed_t *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe, + int interval, int load) { 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"); @@ -784,22 +799,22 @@ static ed_t * ep_add_ed (struct usb_devi }
if (ed->state == ED_NEW) { - ed->hwINFO = m32_swap (OHCI_ED_SKIP); /* skip ed */ /* dummy td; end of td list for ed */ - td = td_alloc (usb_dev); - ed->hwTailP = m32_swap ((unsigned long)td); + td = td_alloc(usb_dev); + ed->hwTailP = m32_swap((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 = m32_swap (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 = m32_swap(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);
if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) { ed->int_period = interval; @@ -815,7 +830,7 @@ static ed_t * ep_add_ed (struct usb_devi
/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
-static void td_fill (ohci_t *ohci, unsigned int info, +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) { @@ -833,29 +848,32 @@ static void td_fill (ohci_t *ohci, unsig td_pt->hwNextTD = 0;
/* fill the old dummy TD */ - td = urb_priv->td [index] = (td_t *)(m32_swap (urb_priv->ed->hwTailP) & ~0xf); + td = urb_priv->td [index] = + (td_t *)(m32_swap(urb_priv->ed->hwTailP) & ~0xf);
td->ed = urb_priv->ed; td->next_dl_td = NULL; td->index = index; 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 = m32_swap (info); - td->hwCBP = m32_swap ((unsigned long)data); + td->hwINFO = m32_swap(info); + td->hwCBP = m32_swap((unsigned long)data); if (data) - td->hwBE = m32_swap ((unsigned long)(data + len - 1)); + td->hwBE = m32_swap((unsigned long)(data + len - 1)); else td->hwBE = 0; - td->hwNextTD = m32_swap ((unsigned long)td_pt); + + td->hwNextTD = m32_swap((unsigned long)td_pt);
/* append to queue */ td->ed->hwTailP = td->hwNextTD; @@ -865,8 +883,10 @@ static void td_fill (ohci_t *ohci, unsig
/* 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; @@ -875,12 +895,14 @@ static void td_submit_job (struct usb_de __u32 info = 0; 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))) { + /* 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))) { 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) @@ -888,44 +910,58 @@ static void td_submit_job (struct usb_de else data = 0;
- switch (usb_pipetype (pipe)) { + switch (usb_pipetype(pipe)) { case PIPE_BULK: - info = usb_pipeout (pipe)? + 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); + 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)? + 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); + 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 */ + if (!ohci->sleeping) { + /* start bulk list */ + writel(OHCI_BLF, &ohci->regs->cmdstatus); + } break;
case PIPE_CONTROL: + /* Setup phase */ 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); + + /* Optional Data phase */ 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); + } + + /* Status phase */ + 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) { + /* start Control list */ + writel(OHCI_CLF, &ohci->regs->cmdstatus); } - 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 */ break;
case PIPE_INTERRUPT: - info = usb_pipeout (urb->pipe)? + info = usb_pipeout(urb->pipe)? TD_CC | TD_DP_OUT | toggle: TD_CC | TD_R | TD_DP_IN | toggle; - td_fill (ohci, info, data, data_len, dev, cnt++, urb); + td_fill(ohci, info, data, data_len, dev, cnt++, urb); break; } if (urb->length != cnt) @@ -938,16 +974,16 @@ static void td_submit_job (struct usb_de
/* calculate the transfer length and update the urb */
-static void dl_transfer_length(td_t * td) +static void dl_transfer_length(td_t *td) { __u32 tdINFO, tdBE, tdCBP; urb_priv_t *lurb_priv = td->ed->purb;
- tdINFO = m32_swap (td->hwINFO); - tdBE = m32_swap (td->hwBE); - tdCBP = m32_swap (td->hwCBP); + tdINFO = m32_swap(td->hwINFO); + tdBE = m32_swap(td->hwBE); + tdCBP = m32_swap(td->hwCBP);
- if (!(usb_pipetype (lurb_priv->pipe) == PIPE_CONTROL && + if (!(usb_pipetype(lurb_priv->pipe) == PIPE_CONTROL && ((td->index == 0) || (td->index == lurb_priv->length - 1)))) { if (tdBE != 0) { if (td->hwCBP == 0) @@ -959,105 +995,128 @@ static void dl_transfer_length(td_t * td }
/*-------------------------------------------------------------------------*/ +static void check_status(td_t *td_list) +{ + urb_priv_t *lurb_priv = td_list->ed->purb; + int urb_len = lurb_priv->length; + __u32 *phwHeadP = &td_list->ed->hwHeadP; + int cc; + + cc = TD_CC_GET(m32_swap(td_list->hwINFO)); + if (cc) { + err(" USB-error: %s (%x)", cc_to_string[cc], cc); + + if (*phwHeadP & m32_swap(0x1)) { + if (lurb_priv && + ((td_list->index + 1) < urb_len)) { + *phwHeadP = + (lurb_priv->td[urb_len - 1]->hwNextTD &\ + m32_swap(0xfffffff0)) | + (*phwHeadP & m32_swap(0x2)); + + lurb_priv->td_cnt += urb_len - + td_list->index - 1; + } else + *phwHeadP &= m32_swap(0xfffffff2); + } +#ifdef CONFIG_MPC5200 + td_list->hwNextTD = 0; +#endif + } +}
/* 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 = m32_swap (ohci->hcca->done_head) & 0xfffffff0; + td_list_hc = m32_swap(ohci->hcca->done_head) & 0xfffffff0; ohci->hcca->done_head = 0;
while (td_list_hc) { td_list = (td_t *)td_list_hc; - - if (TD_CC_GET (m32_swap (td_list->hwINFO))) { - lurb_priv = td_list->ed->purb; - dbg(" USB-error/status: %x : %p", - TD_CC_GET (m32_swap (td_list->hwINFO)), td_list); - if (td_list->ed->hwHeadP & m32_swap (0x1)) { - if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) { - td_list->ed->hwHeadP = - (lurb_priv->td[lurb_priv->length - 1]->hwNextTD & m32_swap (0xfffffff0)) | - (td_list->ed->hwHeadP & m32_swap (0x2)); - lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1; - } else - td_list->ed->hwHeadP &= m32_swap (0xfffffff2); - } -#ifdef CONFIG_MPC5200 - td_list->hwNextTD = 0; -#endif - } - + check_status(td_list); td_list->next_dl_td = td_rev; td_rev = td_list; - td_list_hc = m32_swap (td_list->hwNextTD) & 0xfffffff0; + td_list_hc = m32_swap(td_list->hwNextTD) & 0xfffffff0; } return td_list; }
/*-------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------*/
-/* td done list */ -static int dl_done_list (ohci_t *ohci, td_t *td_list) +static void finish_urb(ohci_t *ohci, urb_priv_t *urb, int status) +{ + if ((status & (ED_OPER | ED_UNLINK)) && (urb->state != URB_DEL)) + urb->finished = sohci_return_job(ohci, urb); + else + dbg("finish_urb: strange.., ED state %x, \n", status); +} + +/* + * Used to take back a TD from the host controller. This would normally be + * called from within dl_done_list, however it may be called directly if the + * HC no longer sees the TD and it has not appeared on the donelist (after + * two frames). This bug has been observed on ZF Micro systems. + */ +static int takeback_td(ohci_t *ohci, td_t *td_list) { - td_t *td_list_next = NULL; ed_t *ed; - int cc = 0; + int cc; int stat = 0; /* urb_t *urb; */ urb_priv_t *lurb_priv; __u32 tdINFO, edHeadP, edTailP;
- while (td_list) { - td_list_next = td_list->next_dl_td; + tdINFO = m32_swap(td_list->hwINFO);
- tdINFO = m32_swap (td_list->hwINFO); + ed = td_list->ed; + lurb_priv = ed->purb;
- ed = td_list->ed; - lurb_priv = ed->purb; + dl_transfer_length(td_list);
- dl_transfer_length(td_list); + lurb_priv->td_cnt++;
- /* error code of transfer */ - cc = TD_CC_GET (tdINFO); - if (cc != 0) { - dbg("ConditionCode %#x", cc); - stat = cc_to_error[cc]; - } + /* error code of transfer */ + cc = TD_CC_GET(tdINFO); + if (cc) { + err("USB-error: %s (%x)", cc_to_string[cc], cc); + stat = cc_to_error[cc]; + }
- /* see if this done list makes for all TD's of current URB, - * and mark the URB finished if so */ - if (++(lurb_priv->td_cnt) == lurb_priv->length) { -#if 1 - if ((ed->state & (ED_OPER | ED_UNLINK)) && - (lurb_priv->state != URB_DEL)) -#else - if ((ed->state & (ED_OPER | ED_UNLINK))) -#endif - lurb_priv->finished = sohci_return_job(ohci, - lurb_priv); - else - dbg("dl_done_list: strange.., ED state %x, ed->state\n"); - } else - dbg("dl_done_list: processing TD %x, len %x\n", lurb_priv->td_cnt, - lurb_priv->length); - if (ed->state != ED_NEW && - (usb_pipetype (lurb_priv->pipe) != PIPE_INTERRUPT)) { - edHeadP = m32_swap (ed->hwHeadP) & 0xfffffff0; - edTailP = m32_swap (ed->hwTailP); - - /* unlink eds if they are not busy */ - if ((edHeadP == edTailP) && (ed->state == ED_OPER)) - ep_unlink (ohci, ed); - } + /* see if this done list makes for all TD's of current URB, + * and mark the URB finished if so */ + if (lurb_priv->td_cnt == lurb_priv->length) + finish_urb(ohci, lurb_priv, ed->state); + + dbg("dl_done_list: processing TD %x, len %x\n", + lurb_priv->td_cnt, lurb_priv->length); + + if (ed->state != ED_NEW && + (usb_pipetype(lurb_priv->pipe) != PIPE_INTERRUPT)) { + edHeadP = m32_swap(ed->hwHeadP) & 0xfffffff0; + edTailP = m32_swap(ed->hwTailP);
- td_list = td_list_next; + /* unlink eds if they are not busy */ + if ((edHeadP == edTailP) && (ed->state == ED_OPER)) + ep_unlink(ohci, ed); + } + return stat; +} + +static int dl_done_list(ohci_t *ohci) +{ + int stat = 0; + td_t *td_list = dl_reverse_done_list(ohci); + + while (td_list) { + td_t *td_next = td_list->next_dl_td; + stat = takeback_td(ohci, td_list); + td_list = td_next; } return stat; } @@ -1100,7 +1159,7 @@ static __u8 root_hub_config_des[] = 0x01, /* __u8 bConfigurationValue; */ 0x00, /* __u8 iConfiguration; */ 0x40, /* __u8 bmAttributes; - Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ 0x00, /* __u8 MaxPower; */
/* interface */ @@ -1170,14 +1229,17 @@ static unsigned char root_hub_str_index1
#define OK(x) len = (x); break #ifdef DEBUG -#define WR_RH_STAT(x) {info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);} -#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);} +#define WR_RH_STAT(x) {info("WR:status %#8x", (x)); writel((x), \ + &gohci.regs->roothub.status); } +#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, \ + (x)); writel((x), &gohci.regs->roothub.portstatus[wIndex-1]); } #else #define WR_RH_STAT(x) writel((x), &gohci.regs->roothub.status) -#define WR_RH_PORTSTAT(x) writel((x), &gohci.regs->roothub.portstatus[wIndex-1]) +#define WR_RH_PORTSTAT(x) writel((x), \ + &gohci.regs->roothub.portstatus[wIndex-1]) #endif #define RD_RH_STAT roothub_status(&gohci) -#define RD_RH_PORTSTAT roothub_portstatus(&gohci,wIndex-1) +#define RD_RH_PORTSTAT roothub_portstatus(&gohci, wIndex-1)
/* request to virtual root hub */
@@ -1187,13 +1249,13 @@ int rh_check_port_status(ohci_t *control int res;
res = -1; - temp = roothub_a (controller); + temp = roothub_a(controller); ndp = (temp & RH_A_NDP); #ifdef CONFIG_AT91C_PQFP_UHPBUG ndp = (ndp == 2) ? 1:0; #endif 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)) && @@ -1208,7 +1270,7 @@ int rh_check_port_status(ohci_t *control static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, struct devrequest *cmd) { - void * data = buffer; + void *data = buffer; int leni = transfer_len; int len = 0; int stat = 0; @@ -1220,7 +1282,8 @@ static int ohci_submit_rh_msg(struct usb __u16 wLength;
#ifdef DEBUG -pkt_print(NULL, dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe)); +pkt_print(NULL, dev, pipe, buffer, transfer_len, + cmd, "SUB(rh)", usb_pipein(pipe)); #else wait_ms(1); #endif @@ -1230,9 +1293,9 @@ pkt_print(NULL, dev, pipe, buffer, trans }
bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = le16_to_cpu (cmd->value); - wIndex = le16_to_cpu (cmd->index); - wLength = le16_to_cpu (cmd->length); + wValue = le16_to_cpu(cmd->value); + wIndex = le16_to_cpu(cmd->index); + wLength = le16_to_cpu(cmd->length);
info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); @@ -1247,118 +1310,118 @@ pkt_print(NULL, dev, pipe, buffer, trans */
case RH_GET_STATUS: - *(__u16 *) data_buf = cpu_to_le16 (1); OK (2); + *(__u16 *) data_buf = cpu_to_le16(1); + OK(2); case RH_GET_STATUS | RH_INTERFACE: - *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); + *(__u16 *) data_buf = cpu_to_le16(0); + OK(2); case RH_GET_STATUS | RH_ENDPOINT: - *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); + *(__u16 *) data_buf = cpu_to_le16(0); + OK(2); case RH_GET_STATUS | RH_CLASS: - *(__u32 *) data_buf = cpu_to_le32 ( + *(__u32 *) data_buf = cpu_to_le32( RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); - OK (4); + OK(4); case RH_GET_STATUS | RH_OTHER | RH_CLASS: - *(__u32 *) data_buf = cpu_to_le32 (RD_RH_PORTSTAT); OK (4); + *(__u32 *) data_buf = cpu_to_le32(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 ); - wait_ms(100); - 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); + wait_ms(100); + 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 */ + 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) { 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) { - 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); + leni, + min_t(unsigned int, + sizeof(root_hub_str_index0), + wLength)); + data_buf = root_hub_str_index0; + OK(len); } - default: - stat = USB_ST_STALLED; + 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; } break;
case RH_GET_DESCRIPTOR | RH_CLASS: { - __u32 temp = roothub_a (&gohci); + __u32 temp = roothub_a(&gohci);
data_buf [0] = 9; /* min length; */ data_buf [1] = 0x29; @@ -1371,13 +1434,13 @@ pkt_print(NULL, dev, pipe, buffer, trans 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? */ + 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); + temp = roothub_b(&gohci); data_buf [7] = temp & RH_B_DR; if (data_buf [2] < 7) { data_buf [8] = 0xff; @@ -1389,32 +1452,33 @@ pkt_print(NULL, dev, pipe, buffer, trans
len = min_t(unsigned int, leni, min_t(unsigned int, data_buf [0], wLength)); - OK (len); + 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); #else wait_ms(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 - pkt_print(NULL, dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); + pkt_print(NULL, dev, pipe, buffer, + transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); #else wait_ms(1); #endif @@ -1451,7 +1515,8 @@ int submit_common_msg(struct usb_device
#ifdef DEBUG urb->actual_length = 0; - pkt_print(urb, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); + pkt_print(urb, dev, pipe, buffer, transfer_len, + setup, "SUB", usb_pipein(pipe)); #else wait_ms(1); #endif @@ -1473,7 +1538,7 @@ int submit_common_msg(struct usb_device
/* 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) + if (usb_pipetype(pipe) == PIPE_BULK) timeout = BULK_TO; else timeout = 100; @@ -1504,7 +1569,7 @@ int submit_common_msg(struct usb_device if (--timeout) { wait_ms(1); if (!urb->finished) - dbg("%"); + dbg("*");
} else { err("CTL:TIMEOUT "); @@ -1519,14 +1584,15 @@ int submit_common_msg(struct usb_device dev->act_len = transfer_len;
#ifdef DEBUG - pkt_print(urb, dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe)); + pkt_print(urb, dev, pipe, buffer, transfer_len, + setup, "RET(ctlr)", usb_pipein(pipe)); #else wait_ms(1); #endif
/* free TDs in urb_priv */ - if (usb_pipetype (pipe) != PIPE_INTERRUPT) - urb_free_priv (urb); + if (usb_pipetype(pipe) != PIPE_INTERRUPT) + urb_free_priv(urb); return 0; }
@@ -1545,7 +1611,8 @@ int submit_control_msg(struct usb_device
info("submit_control_msg"); #ifdef DEBUG - pkt_print(NULL, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); + pkt_print(NULL, dev, pipe, buffer, transfer_len, + setup, "SUB", usb_pipein(pipe)); #else wait_ms(1); #endif @@ -1578,7 +1645,7 @@ int submit_int_msg(struct usb_device *de
/* reset the HC and BUS */
-static int hc_reset (ohci_t *ohci) +static int hc_reset(ohci_t *ohci) { #ifdef CONFIG_PCI_EHCI_DEVNO pci_dev_t pdev; @@ -1599,7 +1666,7 @@ static int hc_reset (ohci_t *ohci) int timeout = 1000;
pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base); - writel (readl(base + EHCI_USBCMD_OFF) | EHCI_USBCMD_HCRESET, + writel(readl(base + EHCI_USBCMD_OFF) | EHCI_USBCMD_HCRESET, base + EHCI_USBCMD_OFF);
while (readl(base + EHCI_USBCMD_OFF) & EHCI_USBCMD_HCRESET) { @@ -1612,11 +1679,12 @@ static int hc_reset (ohci_t *ohci) } else printf("No EHCI func at %d index!\n", CONFIG_PCI_EHCI_DEVNO); #endif - 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; @@ -1625,7 +1693,7 @@ 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 ;\n", ohci->slot_name, @@ -1633,16 +1701,16 @@ static int hc_reset (ohci_t *ohci)
/* 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; } @@ -1653,7 +1721,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; @@ -1663,44 +1731,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); + 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, + writel((roothub_a(ohci) | RH_A_NPS) & ~RH_A_PSM, &ohci->regs->roothub.a); - writel (RH_HS_LPSC, &ohci->regs->roothub.status); + writel(RH_HS_LPSC, &ohci->regs->roothub.status); #endif /* OHCI_USE_NPS */
-#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);}) +#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; @@ -1718,7 +1786,7 @@ void usb_event_poll(void)
/* an interrupt happens */
-static int hc_interrupt (void) +static int hc_interrupt(void) { ohci_t *ohci = &gohci; struct ohci_regs *regs = ohci->regs; @@ -1726,69 +1794,74 @@ static int hc_interrupt (void) int stat = -1;
if ((ohci->hcca->done_head != 0) && - !(m32_swap (ohci->hcca->done_head) & 0x01)) { + !(m32_swap(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; + } else { + ints = readl(®s->intrstatus); + if (ints == ~(u32)0) { + ohci->disabled++; + err("%s device removed!", ohci->slot_name); + return -1; + } else { + ints &= readl(®s->intrenable); + if (ints == 0) { + dbg("hc_interrupt: returning..\n"); + return 0xff; + } + } }
- /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */ + /* dbg("Interrupt: %x frame: %x", ints, + le16_to_cpu(ohci->hcca->frame_no)); */
- if (ints & OHCI_INTR_RHSC) { - got_rhsc = 1; + if (ints & OHCI_INTR_RHSC) stat = 0xff; - }
if (ints & OHCI_INTR_UE) { ohci->disabled++; - err ("OHCI Unrecoverable Error, controller usb-%s disabled", + 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); #else - wait_ms(1); + wait_ms(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) { wait_ms(1); - writel (OHCI_INTR_WDH, ®s->intrdisable); - (void)readl (®s->intrdisable); /* flush */ - stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci)); - writel (OHCI_INTR_WDH, ®s->intrenable); - (void)readl (®s->intrdisable); /* flush */ + writel(OHCI_INTR_WDH, ®s->intrdisable); + (void)readl(®s->intrdisable); /* flush */ + stat = dl_done_list(&gohci); + writel(OHCI_INTR_WDH, ®s->intrenable); + (void)readl(®s->intrdisable); /* flush */ }
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 = m16_swap (ohci->hcca->frame_no) & 1; + unsigned int frame = m16_swap(ohci->hcca->frame_no) & 1; wait_ms(1); - writel (OHCI_INTR_SF, ®s->intrdisable); + 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; }
@@ -1798,12 +1871,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); }
/*-------------------------------------------------------------------------*/ @@ -1821,16 +1894,16 @@ int usb_lowlevel_init(void)
#ifdef CFG_USB_OHCI_CPU_INIT /* cpu dependant init */ - if(usb_cpu_init()) + if (usb_cpu_init()) return -1; #endif
#ifdef CFG_USB_OHCI_BOARD_INIT /* board dependant init */ - if(usb_board_init()) + if (usb_board_init()) return -1; #endif - memset (&gohci, 0, sizeof (ohci_t)); + memset(&gohci, 0, sizeof(ohci_t));
/* align the storage */ if ((__u32)&ghcca[0] & 0xff) { @@ -1851,7 +1924,7 @@ int usb_lowlevel_init(void) } 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; @@ -1879,9 +1952,9 @@ int usb_lowlevel_init(void) gohci.flags = 0; gohci.slot_name = CFG_USB_OHCI_SLOT_NAME;
- if (hc_reset (&gohci) < 0) { - hc_release_ohci (&gohci); - err ("can't reset usb-%s", gohci.slot_name); + if (hc_reset(&gohci) < 0) { + hc_release_ohci(&gohci); + err("can't reset usb-%s", gohci.slot_name); #ifdef CFG_USB_OHCI_BOARD_INIT /* board dependant cleanup */ usb_board_init_fail(); @@ -1894,12 +1967,9 @@ int usb_lowlevel_init(void) return -1; }
- /* FIXME this is a second HC reset; why?? */ - /* writel(gohci.hc_control = OHCI_USB_RESET, &gohci.regs->control); - wait_ms(10); */ - 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); /* Initialization failed */ #ifdef CFG_USB_OHCI_BOARD_INIT /* board dependant cleanup */ @@ -1914,7 +1984,7 @@ int usb_lowlevel_init(void) }
#ifdef DEBUG - ohci_dump (&gohci, 1); + ohci_dump(&gohci, 1); #else wait_ms(1); #endif @@ -1930,17 +2000,17 @@ int usb_lowlevel_stop(void) return 0; /* TODO release any interrupts, etc. */ /* call hc_release_ohci() here ? */ - hc_reset (&gohci); + hc_reset(&gohci);
#ifdef CFG_USB_OHCI_BOARD_INIT /* board dependant cleanup */ - if(usb_board_stop()) + if (usb_board_stop()) return -1; #endif
#ifdef CFG_USB_OHCI_CPU_INIT /* cpu dependant cleanup */ - if(usb_cpu_stop()) + if (usb_cpu_stop()) return -1; #endif /* This driver is no longer initialised. It needs a new low-level Index: u-boot/drivers/usb/usb_ohci.h =================================================================== --- u-boot.orig/drivers/usb/usb_ohci.h 2008-09-16 14:32:13.000000000 +0200 +++ u-boot/drivers/usb/usb_ohci.h 2008-09-16 14:39:24.000000000 +0200 @@ -38,6 +38,41 @@ static int cc_to_error[16] = { /* Not Access */ -1 };
+static const char *cc_to_string[16] = { + "No Error", + "CRC: Last data packet from endpoint contained a CRC error.", + "BITSTUFFING: Last data packet from endpoint contained a bit " \ + "stuffing violation", + "DATATOGGLEMISMATCH: Last packet from endpoint had data toggle PID\n" \ + "that did not match the expected value.", + "STALL: TD was moved to the Done Queue because the endpoint returned" \ + " a STALL PID", + "DEVICENOTRESPONDING: Device did not respond to token (IN) or did\n" \ + "not provide a handshake (OUT)", + "PIDCHECKFAILURE: Check bits on PID from endpoint failed on data PID\n"\ + "(IN) or handshake (OUT)", + "UNEXPECTEDPID: Receive PID was not valid when encountered or PID\n" \ + "value is not defined.", + "DATAOVERRUN: The amount of data returned by the endpoint exceeded\n" \ + "either the size of the maximum data packet allowed\n" \ + "from the endpoint (found in MaximumPacketSize field\n" \ + "of ED) or the remaining buffer size.", + "DATAUNDERRUN: The endpoint returned less than MaximumPacketSize\n" \ + "and that amount was not sufficient to fill the\n" \ + "specified buffer", + "reserved1", + "reserved2", + "BUFFEROVERRUN: During an IN, HC received data from endpoint faster\n" \ + "than it could be written to system memory", + "BUFFERUNDERRUN: During an OUT, HC could not retrieve data from\n" \ + "system memory fast enough to keep up with data USB " \ + "data rate.", + "NOT ACCESSED: This code is set by software before the TD is placed" \ + "on a list to be processed by the HC.(1)", + "NOT ACCESSED: This code is set by software before the TD is placed" \ + "on a list to be processed by the HC.(2)", +}; + /* ED States */
#define ED_NEW 0x00

There are several differences between Linux, Windows and U-boot for initialising the USB devices. While analysing the behaviour of U-boot it turned out that U-boot does things really different, and some are wrong (compared to the USB standard).
This patch fixes some errors: * The NEW_init procedure that was already in the code is good, while the old procedure is wrong. See code comments for more info. * On a Control request the data returned by the device can be more than 8 bytes, while the host limits it to 8 bytes. This caused the host to generate a DataOverrun error. This results in a lot of USB sticks not being recognised, and the transmission ended frequently with a CTL:TIMEOUT Error. * Added a flag CONFIG_LEGACY_USB_INIT_SEQ to allow users to use the old init procedure.
Signed-off-by: Remy Bohmer linux@bohmer.net --- common/usb.c | 50 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 20 deletions(-)
Index: u-boot/common/usb.c =================================================================== --- u-boot.orig/common/usb.c 2008-09-16 14:45:57.000000000 +0200 +++ u-boot/common/usb.c 2008-09-16 14:45:58.000000000 +0200 @@ -80,7 +80,8 @@ void usb_scan_devices(void);
int usb_hub_probe(struct usb_device *dev, int ifnum); void usb_hub_reset(void); - +static int hub_port_reset(struct usb_device *dev, int port, + unsigned short *portstat);
/*********************************************************************** * wait_ms @@ -765,20 +766,34 @@ int usb_new_device(struct usb_device *de int tmp; unsigned char tmpbuf[USB_BUFSIZ];
- dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */ - dev->maxpacketsize = 0; /* Default to 8 byte max packet size */ - dev->epmaxpacketin [0] = 8; - dev->epmaxpacketout[0] = 8; - /* We still haven't set the Address yet */ addr = dev->devnum; dev->devnum = 0;
-#undef NEW_INIT_SEQ -#ifdef NEW_INIT_SEQ +#ifdef CONFIG_LEGACY_USB_INIT_SEQ + /* this is the old and known way of initializing devices, it is + * different than what Windows and Linux are doing. Windows and Linux + * both retrieve 64 bytes while reading the device descriptor + * Several USB stick devices report ERR: CTL_TIMEOUT, caused by an + * invalid header while reading 8 bytes as device descriptor. */ + dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */ + dev->maxpacketsize = 0; /* Default to 8 byte max packet size */ + dev->epmaxpacketin [0] = 8; + dev->epmaxpacketout[0] = 8; + + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); + if (err < 8) { + printf("\n USB device not responding, " \ + "giving up (status=%lX)\n",dev->status); + return 1; + } +#else /* this is a Windows scheme of initialization sequence, with double - * reset of the device. Some equipment is said to work only with such - * init sequence; this patch is based on the work by Alan Stern: + * reset of the device (Linux uses the same sequence, but without double + * reset. This double reset is not considered harmful and matches the + * Windows behaviour) + * Some equipment is said to work only with such init sequence; this + * patch is based on the work by Alan Stern: * http://sourceforge.net/mailarchive/forum.php?thread_id=5729457&forum_id=... */ int j; @@ -790,10 +805,13 @@ int usb_new_device(struct usb_device *de /* send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is * only 18 bytes long, this will terminate with a short packet. But if * the maxpacket size is 8 or 16 the device may be waiting to transmit - * some more. */ + * some more, or keeps on retransmitting the 8 byte header. */
desc = (struct usb_device_descriptor *)tmpbuf; - desc->bMaxPacketSize0 = 0; + dev->descriptor.bMaxPacketSize0 = 64; /* Start off at 64 bytes */ + dev->maxpacketsize = 64; /* Default to 64 byte max packet size */ + dev->epmaxpacketin [0] = 64; + dev->epmaxpacketout[0] = 64; for (j = 0; j < 3; ++j) { err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64); if (err < 0) { @@ -824,14 +842,6 @@ int usb_new_device(struct usb_device *de return 1; } } -#else - /* and this is the old and known way of initializing devices */ - err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); - if (err < 8) { - printf("\n USB device not responding, " \ - "giving up (status=%lX)\n", dev->status); - return 1; - } #endif
dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;

Dear Remy,
On Tue, Sep 16, 2008 at 02:55:41PM +0200, Remy Bohmer wrote:
This series is a set of patches that are required to make USB sticks behave robust while using U-Boot on a OHCI host.
Several users complain about ERROR: CTL:TIMEOUT errors while using USB sticks, and while testing many different USB sticks it showed that some were working and many don't. It even showed a compiler dependency while debugging this, where GCC 3.x compilers seemed to work (but not always) and GCC 4.x compilers usually don't. While debugging this (with a USB analyser of course) it turned out that U-boot also made several protocol violations that needed to be solved, these resulted in hanging USB devices and so on.
In a mail thread with Stelian Pop on 28 July it was reported of a known error on Atmel cores that it did not work.
I tested these series on Atmel AT91SAM9261 Core, with the common OHCI driver, GCC 4.2.3 (Code Sourcery G++ Lite 2008q1-126)
REMEMBER: U-boot still supports 1 single USB stick at a time...
Nice work! I'll test and push your patches to the USB repo ASAP (within the next couple of days). I'd welcome any feedback especially from the people who reported the problems you describe.
Thanks for chasing this down!
Best regards
Markus

Dear All,
This is a nice work. I have ported UBoot on TEngine/SH7727 and got this issue. The issue had reported into UBoot mailing list and Remy sent me a patch. And "ERROR: CTL:TIMEOUT errors" could be fixed with his patch. Thank you a lot.
Let me test his update patch again and report the result later.
Best regards,
-----Original Message----- From: Markus Klotzbücher [mailto:mk@denx.de] Sent: Tuesday, September 16, 2008 9:11 PM To: Remy Bohmer Cc: u-boot@lists.denx.de; Wolfgang Denk; Thao To Hieu; Nicolas Ferre; Stelian Pop Subject: Re: [patch 0/3] Improve stability USB memory sticks for the commonOHCI USB layer.
Dear Remy,
On Tue, Sep 16, 2008 at 02:55:41PM +0200, Remy Bohmer wrote:
This series is a set of patches that are required to make USB sticks behave robust while using U-Boot on a OHCI host.
Several users complain about ERROR: CTL:TIMEOUT errors while using USB sticks, and while testing many different USB sticks it showed that some were working and many don't. It even showed a compiler dependency while debugging this, where GCC 3.x compilers seemed to work (but not always) and GCC 4.x compilers usually don't. While debugging this (with a USB analyser of course) it turned out that U-boot also made several protocol violations that needed to be solved, these resulted in hanging USB devices and so on.
In a mail thread with Stelian Pop on 28 July it was reported of a known error on Atmel cores that it did not work.
I tested these series on Atmel AT91SAM9261 Core, with the common OHCI driver, GCC 4.2.3 (Code Sourcery G++ Lite 2008q1-126)
REMEMBER: U-boot still supports 1 single USB stick at a time...
Nice work! I'll test and push your patches to the USB repo ASAP (within the next couple of days). I'd welcome any feedback especially from the people who reported the problems you describe.
Thanks for chasing this down!
Best regards
Markus

Dear Remy,
I added your patches to the USB custodian repository. As I consider these bugfixes I'll send a pull before the next release.
I succesfully tested them on sequoia, but it would be nice to get some more feedback from the others who reported problems.
Best regards Markus

Le mardi 16 septembre 2008 à 14:55 +0200, Remy Bohmer a écrit :
This series is a set of patches that are required to make USB sticks behave robust while using U-Boot on a OHCI host.
Hi,
I gave your patches a run on an AT91CAP9 and had limited success with them (usb seems to work, usb storage do not):
$ egrep FAT|USB include/configs/at91cap9adk.h #define CONFIG_CMD_USB 1 /* USB */ #define CONFIG_USB_OHCI_NEW 1 #define CFG_USB_OHCI_CPU_INIT 1 #define CFG_USB_OHCI_REGS_BASE 0x00700000 /* AT91_BASE_UHP */ #define CFG_USB_OHCI_SLOT_NAME "at91cap9" #define CFG_USB_OHCI_MAX_ROOT_PORTS 2 #define CONFIG_USB_STORAGE 1 #define CONFIG_CMD_FAT 1
...
U-Boot> usb reset (Re)start USB... USB: scanning bus for devices... 2 USB Device(s) found scanning bus for storage devices... 1 Storage Device(s) found U-Boot> usb info 1: Hub, USB Revision 1.10 - OHCI Root Hub - Class: Hub - PacketSize: 8 Configurations: 1 - Vendor: 0x0000 Product 0x0000 Version 0.0 Configuration: 1 - Interfaces: 1 Self Powered 0mA Interface: 0 - Alternate Setting 0, Endpoints: 1 - Class Hub - Endpoint 1 In Interrupt MaxPacket 2 Interval 255ms
2: Mass Storage, USB Revision 2.0 - P Technology USB Mass Storage Device 00000000000743 - Class: (from Interface) Mass Storage - PacketSize: 64 Configurations: 1 - Vendor: 0x1307 Product 0x0163 Version 1.0 Configuration: 1 - Interfaces: 1 Bus Powered 80mA Interface: 0 - Alternate Setting 0, Endpoints: 3 - Class Mass Storage, Transp. SCSI, Bulk only - Endpoint 1 Out Bulk MaxPacket 64 - Endpoint 2 In Bulk MaxPacket 64 - Endpoint 3 In Interrupt MaxPacket 64 Interval 8ms
U-Boot> usb part print_part of 0
Partition Map for USB device 0 -- Partition Type: DOS
Partition Start Sector Num Sectors Type 1 63 1974208 6
print_part of 1 ## Unknown partition table
print_part of 2 ## Unknown partition table
print_part of 3 ## Unknown partition table
print_part of 4 ## Unknown partition table
U-Boot> usb storage Device 0: not available
U-Boot> fatinfo usb 0:1
** Invalid boot device **

Hello Stelian,
I gave your patches a run on an AT91CAP9 and had limited success with them (usb seems to work, usb storage do not):
Does it work without the patches? Is it a regression, or still an improvement?
U-Boot> usb part print_part of 0
Partition Map for USB device 0 -- Partition Type: DOS
Partition Start Sector Num Sectors Type 1 63 1974208 6
print_part of 1 ## Unknown partition table
These errors are normal, 'usb part' seems to look for primary partitions on a USB stick that is formatted as a floppy...
U-Boot> usb storage Device 0: not available
U-Boot> fatinfo usb 0:1
** Invalid boot device **
I have no explanation for this error, it could be related to the filesystem on the USB stick itself. I do not see any errors that USB itself is not working, the problems I fixed were in the USB area, and they solved all the problems I encountered with USB sticks on AT91SAM9261 (OHCI)
I would expect that it would work much better than before on your CPU... Unfortunately I do not have a test environment for AT91CAP9, so I cannot verify this issue here.
Kind Regards,
Remy

Le jeudi 18 septembre 2008 à 16:54 +0200, Remy Bohmer a écrit :
Hello Stelian,
Hi Remy,
I gave your patches a run on an AT91CAP9 and had limited success with them (usb seems to work, usb storage do not):
Does it work without the patches? Is it a regression, or still an improvement?
It is an improvement, without the patches it doesn't work at all
U-Boot> usb part print_part of 0
Partition Map for USB device 0 -- Partition Type: DOS
Partition Start Sector Num Sectors Type 1 63 1974208 6
print_part of 1 ## Unknown partition table
These errors are normal, 'usb part' seems to look for primary partitions on a USB stick that is formatted as a floppy...
U-Boot> usb storage Device 0: not available
What about this one ? Isn't this supposed to say something else ?
U-Boot> fatinfo usb 0:1
** Invalid boot device **
I have no explanation for this error, it could be related to the filesystem on the USB stick itself.
No, the filesystem is ok. (it's a 1GB stick btw).
I do not see any errors that USB itself is not working, the problems I fixed were in the USB area, and they solved all the problems I encountered with USB sticks on AT91SAM9261 (OHCI)
I'll try to test on some other AT91SAM9 boards later today, if I find a few minutes...
Stelian.

Hello Stelian,
Does it work without the patches? Is it a regression, or still an improvement?
It is an improvement, without the patches it doesn't work at all
I am happy to hear that :-)))
So, Markus, please do not let this issue stop you from integrating these patches :-))
U-Boot> usb storage Device 0: not available
What about this one ? Isn't this supposed to say something else ?
I get these messages also, and I did not considered that to be a problem, because everything works... I got these messages from the beginning, even when USB worked on a single USB stick when I compiled everything with GCC 3.4. I will look into it, but I want to make clear that it is not something I broke with my patches.
U-Boot> fatinfo usb 0:1 ** Invalid boot device **
I have no explanation for this error, it could be related to the filesystem on the USB stick itself.
No, the filesystem is ok. (it's a 1GB stick btw).
I have tested with USB sticks in the range of 256 MB up to 8 GB. So, the size should not matter. I tested FAT16 and FAT32. But, there are USB sticks out there that contain actually 2 devices with an internal hub. Some of these work, and some of these do not. It has to do with U-boot only capable of handling 1 USB storage device at a time.
An example of such sticks can be found here (there may also be other manufacturers): http://www.pendrivestore.com/products/pendriveusb2/index.shtml (Notice that from this manufacturer none of the 1GB editions seem to work, however the 8GB and 256 MB versions work properly)
I'll try to test on some other AT91SAM9 boards later today, if I find a few minutes...
Thanks, and I expect to hear some more positive news ;-)))
Kind Regards,
Remy

Le vendredi 19 septembre 2008 à 11:16 +0200, Remy Bohmer a écrit :
I'll try to test on some other AT91SAM9 boards later today, if I find a few minutes...
Thanks, and I expect to hear some more positive news ;-)))
I'm afraid I have more bad news.
I updated my tree to the latest git. I use the ELDK 4.1 arm compiler.
Tested on an AT91SAM9263, with two different USB sticks:
U-Boot> usb reset (Re)start USB... USB: scanning bus for devices... ERROR: USB-error: DEVICENOTRESPONDING: Device did not respond to token (IN) or did not provide a handshake (OUT) (5) ERROR: USB-error: DEVICENOTRESPONDING: Device did not respond to token (IN) or did not provide a handshake (OUT) (5) ERROR: USB-error: DEVICENOTRESPONDING: Device did not respond to token (IN) or did not provide a handshake (OUT) (5) ERROR: USB-error: DEVICENOTRESPONDING: Device did not respond to token (IN) or did not provide a handshake (OUT) (5)
USB device not accepting new address (error=20) 2 USB Device(s) found scanning bus for storage devices... 0 Storage Device(s) found
Without your 3 patches applied, I get:
U-Boot> usb start (Re)start USB... USB: scanning bus for devices... USB device not responding, giving up (status=20) 2 USB Device(s) found scanning bus for storage devices... 0 Storage Device(s) found
Stelian.

Hello Stelian,
Thanks, and I expect to hear some more positive news ;-)))
I'm afraid I have more bad news.
Grmbl, Now my weekend is ruined ;-))))
I updated my tree to the latest git. I use the ELDK 4.1 arm compiler. Tested on an AT91SAM9263, with two different USB sticks: U-Boot> usb reset (Re)start USB... USB: scanning bus for devices... ERROR: USB-error: DEVICENOTRESPONDING: Device did not respond to token (IN) or did not provide a handshake (OUT) (5) ERROR: USB-error: DEVICENOTRESPONDING: Device did not respond to token (IN) or did not provide a handshake (OUT) (5) ERROR: USB-error: DEVICENOTRESPONDING: Device did not respond to token (IN) or did not provide a handshake (OUT) (5) ERROR: USB-error: DEVICENOTRESPONDING: Device did not respond to token (IN) or did not provide a handshake (OUT) (5) USB device not accepting new address (error=20) 2 USB Device(s) found scanning bus for storage devices... 0 Storage Device(s) found Without your 3 patches applied, I get: U-Boot> usb start (Re)start USB... USB: scanning bus for devices... USB device not responding, giving up (status=20) 2 USB Device(s) found scanning bus for storage devices... 0 Storage Device(s) found
Okay, let's summarize this: With and without patches it does not work on AT91CAP9 and AT91SAM9263... (Without my patches you get a less detailed error message...)
There can be several reasons for this: * The USB code never worked on AT91CAP9 and AT91SAM9263 with mainline, so it could be possible that there is some initialisation missing for CAP9 and SAM9263, possible for more CPU's also that did not work before with GCC 3.x. Does not mean the patches are bad, but does mean that it could be possible/likely that these patches do not fix all problems for all boards and all sticks. * Your USB sticks behave (slightly) different than the sticks I tested. Looking at the error code you get, it seems that the USB stick stops responding, after some time of valid communication, at least 5 control requests to EP0 happen successfully before setting the address, so there was communication which died for some reason. This error code is reported by the OHCI controller itself and is out of hands of software, so we can exclude a lot of SW. Notice that just before setting the address the 2nd device reset is done, maybe there is some additional timeout after reset is required for some USB devices.
I want to invest some time in it to debug these issues also, but then I will need your help, because I do not have a SAM9263, CAP9 board so I cannot reproduce your problems here.
I have several ideas where to look, and can create some experimental patches, but before I do that and bother you unnecessary, I would like to get some more information from you about which USB sticks you are using.
Can you please provide me the output of: (even if the command fails) * usb info * usb storage * usb tree * and if possible a 'lsusb -v' output from linux of your USB sticks
Also, it would be very helpful if you would test your sticks on a SAM9261, because that SoC _must_ work. (I tested on AT91SAM9261-EK, and custom board) Then we can relate the problem to a specific USB stick, or to a certain SoC.
Kind Regards,
Remy

Le samedi 20 septembre 2008 à 11:38 +0200, Remy Bohmer a écrit :
Hello Stelian,
Thanks, and I expect to hear some more positive news ;-)))
I'm afraid I have more bad news.
Grmbl, Now my weekend is ruined ;-))))
Sorry for that :)
[...]
Okay, let's summarize this: With and without patches it does not work on AT91CAP9 and AT91SAM9263... (Without my patches you get a less detailed error message...)
Right. However the two board fail with slight different errors iirc.
There can be several reasons for this:
- The USB code never worked on AT91CAP9 and AT91SAM9263 with mainline,
so it could be possible that there is some initialisation missing for CAP9 and SAM9263, possible for more CPU's also that did not work before with GCC 3.x.
Sure. However, I've double checked the Linux initialisation code for the usb host on the AT91 boards and the U-Boot counterparts and there are only a few differences (some VBus GPIOs to set on the AT91SAM9263, an additionnal clock for AT91SAM9261), and I cannot find anything which could go wrong here.
Does not mean the patches are bad, but does mean that it could be possible/likely that these patches do not fix all problems for all boards and all sticks.
Sure.
[...]
I want to invest some time in it to debug these issues also, but then I will need your help, because I do not have a SAM9263, CAP9 board so I cannot reproduce your problems here.
I do have a SAM9263 in front of me waiting for your experimental patches :-)
And I can do some extra tests on other Atmel boards, but this will have to wait a week or so because I won't have access to them before then.
I have several ideas where to look, and can create some experimental patches, but before I do that and bother you unnecessary, I would like to get some more information from you about which USB sticks you are using.
I tested with 2 different USB sticks, a very old 256 MB one and a more recent 1 GB. They behave exactly the same.
Can you please provide me the output of: (even if the command fails)
- usb info
- usb storage
- usb tree
- and if possible a 'lsusb -v' output from linux of your USB sticks
See below.
Also, it would be very helpful if you would test your sticks on a SAM9261, because that SoC _must_ work. (I tested on AT91SAM9261-EK, and custom board) Then we can relate the problem to a specific USB stick, or to a certain SoC.
Hmm, I can do that, but not before September 29.
Stelian.
U-Boot> usb start (Re)start USB... USB: scanning bus for devices... USB device not responding, giving up (status=20) 2 USB Device(s) found scanning bus for storage devices... 0 Storage Device(s) found U-Boot> usb info 1: Hub, USB Revision 1.10 - OHCI Root Hub - Class: Hub - PacketSize: 8 Configurations: 1 - Vendor: 0x0000 Product 0x0000 Version 0.0 Configuration: 1 - Interfaces: 1 Self Powered 0mA Interface: 0 - Alternate Setting 0, Endpoints: 1 - Class Hub - Endpoint 1 In Interrupt MaxPacket 2 Interval 255ms
Configuration: 0 - Interfaces: 0 Bus Powered 0mA
U-Boot> usb storage No storage devices, perhaps not 'usb start'ed..? U-Boot> usb re tree
Device Tree: 1 Hub (12MBit/s, 0mA) | OHCI Root Hub | |+-0 See Interface (12MBit/s, 0mA)
U-Boot> boot [...] at91_ohci at91_ohci: AT91 OHCI at91_ohci at91_ohci: new USB bus registered, assigned bus number 1 at91_ohci at91_ohci: irq 29, io mem 0x00a00000 usb usb1: configuration #1 chosen from 1 choice hub 1-0:1.0: USB hub found hub 1-0:1.0: 2 ports detected Initializing USB Mass Storage driver... usb 1-1: new full speed USB device using at91_ohci and address 2 usb 1-1: configuration #1 chosen from 1 choice scsi0 : SCSI emulation for USB Mass Storage devices usbcore: registered new interface driver usb-storage USB Mass Storage support registered. [...] scsi 0:0:0:0: Direct-Access USB 2.0 Mobile Disk N4S 1.00 PQ: 0 ANSI: 2 sd 0:0:0:0: [sda] 507904 512-byte hardware sectors (260 MB) sd 0:0:0:0: [sda] Write Protect is off sd 0:0:0:0: [sda] Assuming drive cache: write through sd 0:0:0:0: [sda] 507904 512-byte hardware sectors (260 MB) sd 0:0:0:0: [sda] Write Protect is off sd 0:0:0:0: [sda] Assuming drive cache: write through sda: sda1 sd 0:0:0:0: [sda] Attached SCSI removable disk [...] at91sam9263ek login: root root@at91sam9263ek:~$ lsusb -v
Bus 001 Device 002: ID 126f:1325 TwinMOS Mobile Disk Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x126f TwinMOS idProduct 0x1325 Mobile Disk bcdDevice 1.00 iManufacturer 16 TTI-WDE iProduct 32 USB 2.0 Mobile Disk iSerial 48 FF04112100886 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 39 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 64 iCfg bmAttributes 0x80 MaxPower 100mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 3 bInterfaceClass 8 Mass Storage bInterfaceSubClass 6 SCSI bInterfaceProtocol 80 Bulk (Zip) iInterface 96 BULK Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 255 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x02 EP 2 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 255 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x83 EP 3 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0002 1x 2 bytes bInterval 1 Device Qualifier (for other device speed): bLength 10 bDescriptorType 6 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 bNumConfigurations 1
Bus 001 Device 001: ID 0000:0000 Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 9 Hub bDeviceSubClass 0 Unused bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x0000 idProduct 0x0000 bcdDevice 2.06 iManufacturer 3 Linux 2.6.22 ohci_hcd iProduct 2 AT91 OHCI iSerial 1 at91 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 25 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0xe0 Self Powered Remote Wakeup MaxPower 0mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 9 Hub bInterfaceSubClass 0 Unused bInterfaceProtocol 0 iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0002 1x 2 bytes bInterval 255 Hub Descriptor: bLength 9 bDescriptorType 41 nNbrPorts 2 wHubCharacteristic 0x0012 No power switching (usb 1.0) No overcurrent protection bPwrOn2PwrGood 2 * 2 milli seconds bHubContrCurrent 0 milli Ampere DeviceRemovable 0x00 PortPwrCtrlMask 0x00 Hub Port Status: Port 1: 0000.0103 power enable connect Port 2: 0000.0100 power root@at91sam9263ek:~$

Hi Remy,
Sorry it took so long but here are the results of the tests on my AT91SAM9261-EK.
Le samedi 20 septembre 2008 à 22:14 +0200, Stelian Pop a écrit :
Also, it would be very helpful if you would test your sticks on a SAM9261, because that SoC _must_ work. (I tested on AT91SAM9261-EK, and custom board) Then we can relate the problem to a specific USB stick, or to a
certain SoC.
Hmm, I can do that, but not before September 29.
The stick is fine, it does work ok on the 9261:
usb reset (Re)start USB... USB: scanning bus for devices... New Device 0 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x40 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x40 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x40 set address 1 usb_control_msg: request: 0x5, requesttype: 0x0, value 0x1 index 0x0 length 0x0 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x12 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x200 index 0x0 length 0x8 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x200 index 0x0 length 0x19 get_conf_no 0 Result 25, wLength 25 if 0, ep 0 ##EP epmaxpacketin[1] = 2 set configuration 1 usb_control_msg: request: 0x9, requesttype: 0x0, value 0x1 index 0x0 length 0x0 new device strings: Mfr=0, Product=1, SerialNumber=0 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x300 index 0x0 length 0xFF USB device number 1 default language ID 0x409 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x301 index 0x409 length 0xFF Manufacturer Product OHCI Root Hub SerialNumber usb_control_msg: request: 0x6, requesttype: 0xA0, value 0x2900 index 0x0 length 0x4 usb_control_msg: request: 0x6, requesttype: 0xA0, value 0x2900 index 0x0 length 0x9 usb_control_msg: request: 0x0, requesttype: 0xA0, value 0x0 index 0x0 length 0x4 usb_control_msg: request: 0x3, requesttype: 0x23, value 0x8 index 0x1 length 0x0 usb_control_msg: request: 0x3, requesttype: 0x23, value 0x8 index 0x2 length 0x0 usb_control_msg: request: 0x0, requesttype: 0xA3, value 0x0 index 0x1 length 0x4 usb_control_msg: request: 0x0, requesttype: 0xA3, value 0x0 index 0x1 length 0x4 usb_control_msg: request: 0x1, requesttype: 0x23, value 0x10 index 0x1 length 0x0 usb_control_msg: request: 0x3, requesttype: 0x23, value 0x4 index 0x1 length 0x0 usb_control_msg: request: 0x0, requesttype: 0xA3, value 0x0 index 0x1 length 0x4 usb_control_msg: request: 0x1, requesttype: 0x23, value 0x14 index 0x1 length 0x0 New Device 1 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x40 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x40 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x40 usb_control_msg: request: 0x3, requesttype: 0x23, value 0x4 index 0x1 length 0x0 usb_control_msg: request: 0x0, requesttype: 0xA3, value 0x0 index 0x1 length 0x4 usb_control_msg: request: 0x1, requesttype: 0x23, value 0x14 index 0x1 length 0x0 set address 2 usb_control_msg: request: 0x5, requesttype: 0x0, value 0x2 index 0x0 length 0x0 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x12 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x200 index 0x0 length 0x8 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x200 index 0x0 length 0x27 get_conf_no 0 Result 39, wLength 39 if 0, ep 0 if 0, ep 1 if 0, ep 2 ##EP epmaxpacketout[1] = 64 ##EP epmaxpacketin[2] = 64 ##EP epmaxpacketin[3] = 64 set configuration 1 usb_control_msg: request: 0x9, requesttype: 0x0, value 0x1 index 0x0 length 0x0 new device strings: Mfr=1, Product=2, SerialNumber=3 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x300 index 0x0 length 0xFF USB device number 2 default language ID 0x409 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x301 index 0x409 length 0xFF usb_control_msg: request: 0x6, requesttype: 0x80, value 0x302 index 0x409 length 0xFF usb_control_msg: request: 0x6, requesttype: 0x80, value 0x303 index 0x409 length 0xFF Manufacturer P Technology Product USB Mass Storage Device SerialNumber 00000000000722 usb_control_msg: request: 0x0, requesttype: 0xA3, value 0x0 index 0x2 length 0x4 2 USB Device(s) found scanning bus for storage devices... usb_control_msg: request: 0xFF, requesttype: 0x21, value 0x0 index 0x0 length 0x0 usb_control_msg: request: 0x1, requesttype: 0x2, value 0x0 index 0x82 length 0x0 usb_control_msg: request: 0x1, requesttype: 0x2, value 0x0 index 0x1 length 0x0 1 Storage Device(s) found U-Boot> usb storage Device 0: Vendor: UT163 Rev: 0.00 Prod: USB Flash Disk Type: Removable Hard Disk Capacity: 963.9 MB = 0.9 GB (1974271 x 512) U-Boot> U-Boot> fatls usb 0 1 . 51878326 download.tgz 20351 tp.tgz
2 file(s), 0 dir(s)
U-Boot>

Hello Stelian,
Hmm, I can do that, but not before September 29.
The stick is fine, it does work ok on the 9261:
Thanks for testing it, it sounds good... But that does mean that there is a SoC dependant issue here... I looked at the code again, and found an oddity that I overlooked before and that I need to investigate some more when I have our USB analyser back. It could explain different behaviour across different OHCI controllers.
I will keep you informed when I have more news. (maybe tomorrow, or else beginning next week)
Kind Regards,
Remy
usb reset (Re)start USB... USB: scanning bus for devices... New Device 0 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x40 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x40 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x40 set address 1 usb_control_msg: request: 0x5, requesttype: 0x0, value 0x1 index 0x0 length 0x0 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x12 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x200 index 0x0 length 0x8 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x200 index 0x0 length 0x19 get_conf_no 0 Result 25, wLength 25 if 0, ep 0 ##EP epmaxpacketin[1] = 2 set configuration 1 usb_control_msg: request: 0x9, requesttype: 0x0, value 0x1 index 0x0 length 0x0 new device strings: Mfr=0, Product=1, SerialNumber=0 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x300 index 0x0 length 0xFF USB device number 1 default language ID 0x409 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x301 index 0x409 length 0xFF Manufacturer Product OHCI Root Hub SerialNumber usb_control_msg: request: 0x6, requesttype: 0xA0, value 0x2900 index 0x0 length 0x4 usb_control_msg: request: 0x6, requesttype: 0xA0, value 0x2900 index 0x0 length 0x9 usb_control_msg: request: 0x0, requesttype: 0xA0, value 0x0 index 0x0 length 0x4 usb_control_msg: request: 0x3, requesttype: 0x23, value 0x8 index 0x1 length 0x0 usb_control_msg: request: 0x3, requesttype: 0x23, value 0x8 index 0x2 length 0x0 usb_control_msg: request: 0x0, requesttype: 0xA3, value 0x0 index 0x1 length 0x4 usb_control_msg: request: 0x0, requesttype: 0xA3, value 0x0 index 0x1 length 0x4 usb_control_msg: request: 0x1, requesttype: 0x23, value 0x10 index 0x1 length 0x0 usb_control_msg: request: 0x3, requesttype: 0x23, value 0x4 index 0x1 length 0x0 usb_control_msg: request: 0x0, requesttype: 0xA3, value 0x0 index 0x1 length 0x4 usb_control_msg: request: 0x1, requesttype: 0x23, value 0x14 index 0x1 length 0x0 New Device 1 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x40 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x40 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x40 usb_control_msg: request: 0x3, requesttype: 0x23, value 0x4 index 0x1 length 0x0 usb_control_msg: request: 0x0, requesttype: 0xA3, value 0x0 index 0x1 length 0x4 usb_control_msg: request: 0x1, requesttype: 0x23, value 0x14 index 0x1 length 0x0 set address 2 usb_control_msg: request: 0x5, requesttype: 0x0, value 0x2 index 0x0 length 0x0 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x100 index 0x0 length 0x12 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x200 index 0x0 length 0x8 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x200 index 0x0 length 0x27 get_conf_no 0 Result 39, wLength 39 if 0, ep 0 if 0, ep 1 if 0, ep 2 ##EP epmaxpacketout[1] = 64 ##EP epmaxpacketin[2] = 64 ##EP epmaxpacketin[3] = 64 set configuration 1 usb_control_msg: request: 0x9, requesttype: 0x0, value 0x1 index 0x0 length 0x0 new device strings: Mfr=1, Product=2, SerialNumber=3 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x300 index 0x0 length 0xFF USB device number 2 default language ID 0x409 usb_control_msg: request: 0x6, requesttype: 0x80, value 0x301 index 0x409 length 0xFF usb_control_msg: request: 0x6, requesttype: 0x80, value 0x302 index 0x409 length 0xFF usb_control_msg: request: 0x6, requesttype: 0x80, value 0x303 index 0x409 length 0xFF Manufacturer P Technology Product USB Mass Storage Device SerialNumber 00000000000722 usb_control_msg: request: 0x0, requesttype: 0xA3, value 0x0 index 0x2 length 0x4 2 USB Device(s) found scanning bus for storage devices... usb_control_msg: request: 0xFF, requesttype: 0x21, value 0x0 index 0x0 length 0x0 usb_control_msg: request: 0x1, requesttype: 0x2, value 0x0 index 0x82 length 0x0 usb_control_msg: request: 0x1, requesttype: 0x2, value 0x0 index 0x1 length 0x0 1 Storage Device(s) found U-Boot> usb storage Device 0: Vendor: UT163 Rev: 0.00 Prod: USB Flash Disk Type: Removable Hard Disk Capacity: 963.9 MB = 0.9 GB (1974271 x 512) U-Boot> U-Boot> fatls usb 0 1 . 51878326 download.tgz 20351 tp.tgz
2 file(s), 0 dir(s)
U-Boot>
-- Stelian Pop stelian@popies.net

Dear Remy Bohmer,
In message 3efb10970809190216x65954093h52610ba9bfdc6ec7@mail.gmail.com you wrote:
U-Boot> usb storage Device 0: not available
What about this one ? Isn't this supposed to say something else ?
I get these messages also, and I did not considered that to be a problem, because everything works...
Oh, but this *is* a problem. It is not the normal output of that command.
I will look into it, but I want to make clear that it is not something I broke with my patches.
OK. But it is an unsolved problem.
I have tested with USB sticks in the range of 256 MB up to 8 GB. So, the size should not matter. I tested FAT16 and FAT32.
Indeed, size should not matter at all. Also, the file system type should not matter at all at this stage.
Partitioning might have in influence int he later steps [even though it should not, i. e. any issues popping up there are more items on the list of things that need to be fixed].
Thanks.
Best regards,
Wolfgang Denk

Hello Wolfgang,
I get these messages also, and I did not considered that to be a problem, because everything works...
Oh, but this *is* a problem. It is not the normal output of that command.
Yeah, I agree, it was a problem, but this is what I meant: During debugging it was not related to the problem I was debugging, therefor I considered it was no problem (for me) at that time...
I will look into it, but I want to make clear that it is not something
I broke with my patches.
OK. But it is an unsolved problem.
No, it was already solved in latest git. I started debugging on a 2 week old git version which did not contain that fix. Markus pointed us already to the fix. However, the fix in mainline was not complete, therefor I made a patch to make it complete... (should be in your mailbox)
I have tested with USB sticks in the range of 256 MB up to 8 GB. So, the size should not matter. I tested FAT16 and FAT32.
Indeed, size should not matter at all. Also, the file system type should not matter at all at this stage.
No, but the weird thing is that I had (new) USB sticks in the beginning that only started to work after a reformat... Very strange, but true. Now (with my USB patches) these issues are solved, and it makes no difference anymore...
Partitioning might have in influence int he later steps [even though it should not, i. e. any issues popping up there are more items on the list of things that need to be fixed].
Agree.
Kind Regards,
Remy

Hello Stelian,
U-Boot> usb storage Device 0: not available
What about this one ? Isn't this supposed to say something else ?
I got it! Currently the IF_TYPE_USB is not handled in the dev_print routine in part.c It is just a info printing issue, not a real functional bug.
I am working on a patch. It will be a separate standalone patch.
Kind Regards,
Remy
U-Boot> fatinfo usb 0:1
** Invalid boot device **
I have no explanation for this error, it could be related to the filesystem on the USB stick itself.
No, the filesystem is ok. (it's a 1GB stick btw).
I do not see any errors that USB itself is not working, the problems I fixed were in the USB area, and they solved all the problems I encountered with USB sticks on AT91SAM9261 (OHCI)
I'll try to test on some other AT91SAM9 boards later today, if I find a few minutes...
Stelian.
Stelian Pop stelian@popies.net

On Fri, Sep 19, 2008 at 11:45:44AM +0200, Remy Bohmer wrote:
U-Boot> usb storage Device 0: not available
What about this one ? Isn't this supposed to say something else ?
I got it! Currently the IF_TYPE_USB is not handled in the dev_print routine in part.c It is just a info printing issue, not a real functional bug.
Are you guys working on top of git? Doesn't the following commit fix this already?
commit 47bebe34ca4e33bab0e822e4ceebbec2590ccbcb Author: Nícolas Carneiro Lebedenco nicolas.lebedenco@tasksistemas.com.br Date: Thu Sep 4 15:35:46 2008 -0300
Fix dev_print when called from usb_stor_info (usb storage command)
Fix output of the usb storage command. It was printing "Device 0: not available" because IF_TYPE_USB was not included into the switch statement.
Signed-off-by: Nicolas Lebedenco nicolas.lebedenco@tasksistemas.com.br
Best regards Markus

Hello Markus,
Are you guys working on top of git? Doesn't the following commit fix this already?
uuuh, I am not updating daily... But, I verified and publish my patches always on latest git, but that is something different than using the latest git in our product on daily base... So, I did not notice this change...
Thanks for the hint...
Kind Regards,
Remy
commit 47bebe34ca4e33bab0e822e4ceebbec2590ccbcb Author: Nícolas Carneiro Lebedenco nicolas.lebedenco@tasksistemas.com.br Date: Thu Sep 4 15:35:46 2008 -0300
Fix dev_print when called from usb_stor_info (usb storage command)
Fix output of the usb storage command. It was printing "Device 0: not available" because IF_TYPE_USB was not included into the switch statement.
Signed-off-by: Nicolas Lebedenco nicolas.lebedenco@tasksistemas.com.br
Best regards Markus
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-0 Fax: +49-8142-66989-80 Email: office@denx.de")

Hello Stelian,
I gave your patches a run on an AT91CAP9 and had limited success with them (usb seems to work, usb storage do not):
Does it work without the patches? Is it a regression, or still an improvement?
U-Boot> usb part print_part of 0
Partition Map for USB device 0 -- Partition Type: DOS
Partition Start Sector Num Sectors Type 1 63 1974208 6
print_part of 1 ## Unknown partition table
These errors are normal, 'usb part' seems to look for primary partitions on a USB stick that is formatted as a floppy...
U-Boot> usb storage Device 0: not available
U-Boot> fatinfo usb 0:1
** Invalid boot device **
I have no explanation for this error, it could be related to the filesystem on the USB stick itself. I do not see any errors that USB itself is not working, the problems I fixed were in the USB area, and they solved all the problems I encountered with USB sticks on AT91SAM9261 (OHCI)
I would expect that it would work much better than before on your CPU... Unfortunately I do not have a test environment for AT91CAP9, so I cannot verify this issue here.
Kind Regards,
Remy
participants (5)
-
Markus Klotzbücher
-
Remy Bohmer
-
Stelian Pop
-
Thao To Hieu
-
Wolfgang Denk