<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">From: Greg KH &lt;greg@kroah.com&gt;
To: torvalds@transmeta.com
Cc: linux-usb-devel@lists.sourceforge.net
Subject: [PATCH 9 of 9] USB ohci-hcd driver update

Hi,

Here's a patch against 2.5.3 for the USB ohci-hcd driver that does the
following:
	- doesn't assume CONFIG_DEBUG_SLAB
	- unlink from interrupt completions now work
	- doesn't force debugging on
	- updated copyright / license statements
	- slightly smaller object size
	- fewer inlined magic numbers
	- removes unused fields from data structures
	- header file reorg, doc fixup
This patch was done by David Brownell.

thanks,

greg k-h



diff -Nru a/drivers/usb/hcd/ohci-dbg.c b/drivers/usb/hcd/ohci-dbg.c
--- a/drivers/usb/hcd/ohci-dbg.c	Sun Feb  3 00:53:05 2002
+++ b/drivers/usb/hcd/ohci-dbg.c	Sun Feb  3 00:53:05 2002
@@ -2,9 +2,9 @@
  * OHCI HCD (Host Controller Driver) for USB.
  * 
  * (C) Copyright 1999 Roman Weissgaerber &lt;weissg@vienna.at&gt;
- * (C) Copyright 2000-2001 David Brownell &lt;dbrownell@users.sourceforge.net&gt;
+ * (C) Copyright 2000-2002 David Brownell &lt;dbrownell@users.sourceforge.net&gt;
  * 
- * This file is licenced under GPL
+ * This file is licenced under the GPL.
  * $Id: ohci-dbg.c,v 1.2 2002/01/19 00:15:45 dbrownell Exp $
  */
  
@@ -74,27 +74,34 @@
 static inline struct ed *
 dma_to_ed (struct ohci_hcd *hc, dma_addr_t ed_dma);
 
+#ifdef OHCI_VERBOSE_DEBUG
 /* print non-empty branches of the periodic ed tree */
-void ep_print_int_eds (struct ohci_hcd *ohci, char * str)
+void ohci_dump_periodic (struct ohci_hcd *ohci, char *label)
 {
 	int i, j;
-	 __u32 * ed_p;
+	u32 *ed_p;
+	int printed = 0;
+
 	for (i= 0; i &lt; 32; i++) {
 		j = 5;
 		ed_p = &amp;(ohci-&gt;hcca-&gt;int_table [i]);
 		if (*ed_p == 0)
-		    continue;
-		printk (KERN_DEBUG __FILE__ ": %s branch int %2d(%2x):",
-				str, i, i);
+			continue;
+		printed = 1;
+		printk (KERN_DEBUG "%s, ohci %s frame %2d:",
+				label, ohci-&gt;hcd.bus_name, i);
 		while (*ed_p != 0 &amp;&amp; j--) {
 			struct ed *ed = dma_to_ed (ohci, le32_to_cpup(ed_p));
-			printk (" ed: %4x;", ed-&gt;hwINFO);
+			printk (" %p/%08x;", ed, ed-&gt;hwINFO);
 			ed_p = &amp;ed-&gt;hwNextED;
 		}
 		printk ("\n");
 	}
+	if (!printed)
+		printk (KERN_DEBUG "%s, ohci %s, empty periodic schedule\n",
+				label, ohci-&gt;hcd.bus_name);
 }
-
+#endif
 
 static void ohci_dump_intr_mask (char *label, __u32 mask)
 {
@@ -137,8 +144,9 @@
 	__u32			temp;
 
 	temp = readl (&amp;regs-&gt;revision) &amp; 0xff;
-	if (temp != 0x10)
-		dbg ("spec %d.%d", (temp &gt;&gt; 4), (temp &amp; 0x0f));
+	dbg ("OHCI %d.%d, %s legacy support registers",
+		0x03 &amp; (temp &gt;&gt; 4), (temp &amp; 0x0f),
+		(temp &amp; 0x10) ? "with" : "NO");
 
 	temp = readl (&amp;regs-&gt;control);
 	dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp,
@@ -225,8 +233,10 @@
 
 	// dumps some of the state we know about
 	ohci_dump_status (controller);
+#ifdef OHCI_VERBOSE_DEBUG
 	if (verbose)
-		ep_print_int_eds (controller, "hcca");
+		ohci_dump_periodic (controller, "hcca");
+#endif
 	dbg ("hcca frame #%04x", controller-&gt;hcca-&gt;frame_no);
 	ohci_dump_roothub (controller, 1);
 }
diff -Nru a/drivers/usb/hcd/ohci-hcd.c b/drivers/usb/hcd/ohci-hcd.c
--- a/drivers/usb/hcd/ohci-hcd.c	Sun Feb  3 00:53:05 2002
+++ b/drivers/usb/hcd/ohci-hcd.c	Sun Feb  3 00:53:05 2002
@@ -2,7 +2,7 @@
  * OHCI HCD (Host Controller Driver) for USB.
  *
  * (C) Copyright 1999 Roman Weissgaerber &lt;weissg@vienna.at&gt;
- * (C) Copyright 2000-2001 David Brownell &lt;dbrownell@users.sourceforge.net&gt;
+ * (C) Copyright 2000-2002 David Brownell &lt;dbrownell@users.sourceforge.net&gt;
  * 
  * [ Initialisation is based on Linus'  ]
  * [ uhci code and gregs ohci fragments ]
@@ -55,7 +55,7 @@
  * v2.0 1999/05/04 
  * v1.0 1999/04/27 initial release
  *
- * This file is licenced under GPL
+ * This file is licenced under the GPL.
  * $Id: ohci-hcd.c,v 1.7 2002/01/19 00:20:56 dbrownell Exp $
  */
  
@@ -74,10 +74,6 @@
 #include &lt;linux/list.h&gt;
 #include &lt;linux/interrupt.h&gt;  /* for in_interrupt () */
 
-#ifndef CONFIG_USB_DEBUG
-	#define CONFIG_USB_DEBUG	/* this is still experimental! */
-#endif
-
 #ifdef CONFIG_USB_DEBUG
 	#define DEBUG
 #else
@@ -258,7 +254,9 @@
 	if (ed-&gt;state != ED_OPER)
 		ep_link (ohci, ed);
 
-	/* fill the TDs and link it to the ed */
+	/* fill the TDs and link them to the ed; and
+	 * enable that part of the schedule, if needed
+	 */
 	td_submit_urb (urb);
 
 	spin_unlock_irqrestore (&amp;ohci-&gt;lock, flags);
@@ -357,7 +355,9 @@
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 
+#ifdef	OHCI_VERBOSE_DEBUG
 	dbg ("%s: ohci_get_frame", hcd-&gt;bus_name);
+#endif
 	return le16_to_cpu (ohci-&gt;hcca-&gt;frame_no);
 }
 
@@ -841,9 +847,10 @@
 			dl_done_list (ohci, dl_reverse_done_list (ohci));
 		writel (OHCI_INTR_WDH, &amp;ohci-&gt;regs-&gt;intrenable); 
 
-//		writel (OHCI_BLF, &amp;ohci-&gt;regs-&gt;cmdstatus);
-//		writel (OHCI_CLF, &amp;ohci-&gt;regs-&gt;cmdstatus);
-ohci_dump_status (ohci);
+		/* assume there are TDs on the bulk and control lists */
+		writel (OHCI_BLF | OHCI_CLF, &amp;ohci-&gt;regs-&gt;cmdstatus);
+
+// ohci_dump_status (ohci);
 dbg ("sleeping = %d, disabled = %d", ohci-&gt;sleeping, ohci-&gt;disabled);
 		break;
 
diff -Nru a/drivers/usb/hcd/ohci-hub.c b/drivers/usb/hcd/ohci-hub.c
--- a/drivers/usb/hcd/ohci-hub.c	Sun Feb  3 00:53:05 2002
+++ b/drivers/usb/hcd/ohci-hub.c	Sun Feb  3 00:53:05 2002
@@ -2,7 +2,7 @@
  * OHCI HCD (Host Controller Driver) for USB.
  * 
  * (C) Copyright 1999 Roman Weissgaerber &lt;weissg@vienna.at&gt;
- * (C) Copyright 2000-2001 David Brownell &lt;dbrownell@users.sourceforge.net&gt;
+ * (C) Copyright 2000-2002 David Brownell &lt;dbrownell@users.sourceforge.net&gt;
  * 
  * This file is licenced under GPL
  * $Id: ohci-hub.c,v 1.2 2002/01/19 00:21:49 dbrownell Exp $
diff -Nru a/drivers/usb/hcd/ohci-mem.c b/drivers/usb/hcd/ohci-mem.c
--- a/drivers/usb/hcd/ohci-mem.c	Sun Feb  3 00:53:04 2002
+++ b/drivers/usb/hcd/ohci-mem.c	Sun Feb  3 00:53:04 2002
@@ -2,9 +2,9 @@
  * OHCI HCD (Host Controller Driver) for USB.
  * 
  * (C) Copyright 1999 Roman Weissgaerber &lt;weissg@vienna.at&gt;
- * (C) Copyright 2000-2001 David Brownell &lt;dbrownell@users.sourceforge.net&gt;
+ * (C) Copyright 2000-2002 David Brownell &lt;dbrownell@users.sourceforge.net&gt;
  * 
- * This file is licenced under GPL
+ * This file is licenced under the GPL.
  * $Id: ohci-mem.c,v 1.2 2002/01/19 00:22:13 dbrownell Exp $
  */
 
@@ -42,7 +42,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef DEBUG
+#ifdef	CONFIG_DEBUG_SLAB
 #	define OHCI_MEM_FLAGS	SLAB_POISON
 #else
 #	define OHCI_MEM_FLAGS	0
@@ -64,16 +64,17 @@
 	return scan-&gt;virt;
 }
 
-static inline struct ed *
+static struct ed *
 dma_to_ed (struct ohci_hcd *hc, dma_addr_t ed_dma)
 {
 	return (struct ed *) dma_to_ed_td(&amp;(hc-&gt;ed_hash [ED_HASH_FUNC(ed_dma)]),
 				      ed_dma);
 }
 
-static inline struct td *
+static struct td *
 dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
 {
+	td_dma &amp;= TD_MASK;
 	return (struct td *) dma_to_ed_td(&amp;(hc-&gt;td_hash [TD_HASH_FUNC(td_dma)]),
 				      td_dma);
 }
@@ -214,7 +215,7 @@
 	return td;
 }
 
-static inline void
+static void
 td_free (struct ohci_hcd *hc, struct td *td)
 {
 	hash_free_td (hc, td);
@@ -242,7 +243,7 @@
 	return ed;
 }
 
-static inline void
+static void
 ed_free (struct ohci_hcd *hc, struct ed *ed)
 {
 	hash_free_ed (hc, ed);
diff -Nru a/drivers/usb/hcd/ohci-q.c b/drivers/usb/hcd/ohci-q.c
--- a/drivers/usb/hcd/ohci-q.c	Sun Feb  3 00:53:03 2002
+++ b/drivers/usb/hcd/ohci-q.c	Sun Feb  3 00:53:03 2002
@@ -2,9 +2,9 @@
  * OHCI HCD (Host Controller Driver) for USB.
  * 
  * (C) Copyright 1999 Roman Weissgaerber &lt;weissg@vienna.at&gt;
- * (C) Copyright 2000-2001 David Brownell &lt;dbrownell@users.sourceforge.net&gt;
+ * (C) Copyright 2000-2002 David Brownell &lt;dbrownell@users.sourceforge.net&gt;
  * 
- * This file is licenced under GPL
+ * This file is licenced under the GPL.
  * $Id: ohci-q.c,v 1.6 2002/01/19 00:23:15 dbrownell Exp $
  */
  
@@ -95,11 +95,11 @@
 	urb_print (urb, "RET", usb_pipeout (urb-&gt;pipe));
 #endif
 
-// FIXME:  but if urb-&gt;status says it was was unlinked ...
-
 	switch (usb_pipetype (urb-&gt;pipe)) {
   		case PIPE_INTERRUPT:
 #ifdef CONFIG_PCI
+// FIXME rewrite this resubmit path.  use pci_dma_sync_single()
+// and requeue more cheaply, and only if needed.
 			pci_unmap_single (hc-&gt;hcd.pdev,
 				urb_priv-&gt;td [0]-&gt;data_dma,
 				urb-&gt;transfer_buffer_length,
@@ -107,16 +107,22 @@
 					? PCI_DMA_TODEVICE
 					: PCI_DMA_FROMDEVICE);
 #endif
+			/* FIXME: MP race.  If another CPU partially unlinks
+			 * this URB (urb-&gt;status was updated, hasn't yet told
+			 * us to dequeue) before we call complete() here, an
+			 * extra "unlinked" completion will be reported...
+			 */
 			urb-&gt;complete (urb);
 
-			/* implicitly requeued */
+			/* always requeued, but ED_SKIP if complete() unlinks.
+			 * removed from periodic table only at SOF intr.
+			 */
   			urb-&gt;actual_length = 0;
-  			urb-&gt;status = -EINPROGRESS;
-  			if (urb_priv-&gt;state != URB_DEL) {
-				spin_lock_irqsave (&amp;hc-&gt;lock, flags);
-  				td_submit_urb (urb);
-  				spin_unlock_irqrestore (&amp;hc-&gt;lock, flags);
-			}
+			if (urb_priv-&gt;state != URB_DEL)
+				urb-&gt;status = -EINPROGRESS;
+			spin_lock_irqsave (&amp;hc-&gt;lock, flags);
+			td_submit_urb (urb);
+			spin_unlock_irqrestore (&amp;hc-&gt;lock, flags);
   			break;
 
 		case PIPE_ISOCHRONOUS:
@@ -126,7 +132,7 @@
 				continue;
 			if (urbt) { /* send the reply and requeue URB */	
 #ifdef CONFIG_PCI
-// FIXME this style unmap is only done on this route ...
+// FIXME rewrite this resubmit path too
 				pci_unmap_single (hc-&gt;hcd.pdev,
 					urb_priv-&gt;td [0]-&gt;data_dma,
 					urb-&gt;transfer_buffer_length,
@@ -290,8 +296,8 @@
 			ed-&gt;hwNextED = *ed_p; 
 			*ed_p = cpu_to_le32 (ed-&gt;dma);
 		}
-#ifdef DEBUG
-		ep_print_int_eds (ohci, "LINK_INT");
+#ifdef OHCI_VERBOSE_DEBUG
+		ohci_dump_periodic (ohci, "LINK_INT");
 #endif
 		break;
 
@@ -313,8 +319,8 @@
 			ed-&gt;ed_prev = NULL;
 		}	
 		ohci-&gt;ed_isotail = edi;  
-#ifdef DEBUG
-		ep_print_int_eds (ohci, "LINK_ISO");
+#ifdef OHCI_VERBOSE_DEBUG
+		ohci_dump_periodic (ohci, "LINK_ISO");
 #endif
 		break;
 	}	 	
@@ -336,7 +342,7 @@
 	int	interval;
 	__u32	*ed_p;
 
-	ed-&gt;hwINFO |= __constant_cpu_to_le32 (OHCI_ED_SKIP);
+	ed-&gt;hwINFO |= ED_SKIP;
 
 	switch (ed-&gt;type) {
 	case PIPE_CONTROL:
@@ -394,8 +400,8 @@
 		}
 		for (i = int_branch; i &lt; NUM_INTS; i += interval)
 		    ohci-&gt;ohci_int_load [i] -= ed-&gt;int_load;
-#ifdef DEBUG
-		ep_print_int_eds (ohci, "UNLINK_INT");
+#ifdef OHCI_VERBOSE_DEBUG
+		ohci_dump_periodic (ohci, "UNLINK_INT");
 #endif
 		break;
 
@@ -421,11 +427,15 @@
 				}
 			}	
 		}	
-#ifdef DEBUG
-		ep_print_int_eds (ohci, "UNLINK_ISO");
+#ifdef OHCI_VERBOSE_DEBUG
+		ohci_dump_periodic (ohci, "UNLINK_ISO");
 #endif
 		break;
 	}
+
+	/* FIXME ED's "unlink" state is indeterminate;
+	 * the HC might still be caching it (till SOF).
+	 */
 	ed-&gt;state = ED_UNLINK;
 	return 0;
 }
@@ -478,7 +488,7 @@
 	}
 
 	if (ed-&gt;state == ED_NEW) {
-		ed-&gt;hwINFO = __constant_cpu_to_le32 (OHCI_ED_SKIP);
+		ed-&gt;hwINFO = ED_SKIP;
   		/* dummy td; end of td list for ed */
 		td = td_alloc (ohci, SLAB_ATOMIC);
  		if (!td) {
@@ -492,8 +502,6 @@
 		ed-&gt;type = usb_pipetype (pipe);
 	}
 
-	ohci-&gt;dev [usb_pipedevice (pipe)] = udev;
-
 // FIXME:  don't do this if it's linked to the HC,
 // we might clobber data toggle or other state ...
 
@@ -531,7 +539,7 @@
 		return;
 	ed-&gt;state |= ED_URB_DEL;
 
-	ed-&gt;hwINFO |= __constant_cpu_to_le32 (OHCI_ED_SKIP);
+	ed-&gt;hwINFO |= ED_SKIP;
 
 	switch (ed-&gt;type) {
 		case PIPE_CONTROL: /* stop control list */
@@ -582,7 +590,7 @@
 
 	/* fill the old dummy TD */
 	td = urb_priv-&gt;td [index] = dma_to_td (ohci,
-			le32_to_cpup (&amp;urb_priv-&gt;ed-&gt;hwTailP) &amp; ~0xf);
+			le32_to_cpup (&amp;urb_priv-&gt;ed-&gt;hwTailP));
 
 	td-&gt;ed = urb_priv-&gt;ed;
 	td-&gt;next_dl_td = NULL;
@@ -795,7 +803,7 @@
 
   	spin_lock_irqsave (&amp;ohci-&gt;lock, flags);
 
-	td_list_hc = le32_to_cpup (&amp;ohci-&gt;hcca-&gt;done_head) &amp; 0xfffffff0;
+	td_list_hc = le32_to_cpup (&amp;ohci-&gt;hcca-&gt;done_head);
 	ohci-&gt;hcca-&gt;done_head = 0;
 
 	while (td_list_hc) {		
@@ -806,26 +814,24 @@
 			dbg (" USB-error/status: %x : %p", 
 				TD_CC_GET (le32_to_cpup (&amp;td_list-&gt;hwINFO)),
 				td_list);
-			if (td_list-&gt;ed-&gt;hwHeadP
-					&amp; __constant_cpu_to_le32 (0x1)) {
+			/* typically the endpoint halted too */
+			if (td_list-&gt;ed-&gt;hwHeadP &amp; ED_H) {
 				if (urb_priv &amp;&amp; ((td_list-&gt;index + 1)
 						&lt; urb_priv-&gt;length)) {
 					td_list-&gt;ed-&gt;hwHeadP = 
 			    (urb_priv-&gt;td [urb_priv-&gt;length - 1]-&gt;hwNextTD
-				    &amp; __constant_cpu_to_le32 (0xfffffff0))
-			    | (td_list-&gt;ed-&gt;hwHeadP
-				    &amp; __constant_cpu_to_le32 (0x2));
+				    &amp; __constant_cpu_to_le32 (TD_MASK))
+			    | (td_list-&gt;ed-&gt;hwHeadP &amp; ED_C);
 					urb_priv-&gt;td_cnt += urb_priv-&gt;length
 						- td_list-&gt;index - 1;
 				} else 
-					td_list-&gt;ed-&gt;hwHeadP &amp;=
-					__constant_cpu_to_le32 (0xfffffff2);
+					td_list-&gt;ed-&gt;hwHeadP &amp;= ~ED_H;
 			}
 		}
 
 		td_list-&gt;next_dl_td = td_rev;	
 		td_rev = td_list;
-		td_list_hc = le32_to_cpup (&amp;td_list-&gt;hwNextTD) &amp; 0xfffffff0;	
+		td_list_hc = le32_to_cpup (&amp;td_list-&gt;hwNextTD);
 	}	
 	spin_unlock_irqrestore (&amp;ohci-&gt;lock, flags);
 	return td_list;
@@ -851,10 +857,8 @@
 
 	for (ed = ohci-&gt;ed_rm_list [frame]; ed != NULL; ed = ed-&gt;ed_rm_list) {
 
-		tdTailP = dma_to_td (ohci,
-			le32_to_cpup (&amp;ed-&gt;hwTailP) &amp; 0xfffffff0);
-		tdHeadP = dma_to_td (ohci,
-			le32_to_cpup (&amp;ed-&gt;hwHeadP) &amp; 0xfffffff0);
+		tdTailP = dma_to_td (ohci, le32_to_cpup (&amp;ed-&gt;hwTailP));
+		tdHeadP = dma_to_td (ohci, le32_to_cpup (&amp;ed-&gt;hwHeadP));
 		edINFO = le32_to_cpup (&amp;ed-&gt;hwINFO);
 		td_p = &amp;ed-&gt;hwHeadP;
 
@@ -863,7 +867,7 @@
 			urb_priv_t *urb_priv = td-&gt;urb-&gt;hcpriv;
 
 			td_next = dma_to_td (ohci,
-				le32_to_cpup (&amp;td-&gt;hwNextTD) &amp; 0xfffffff0);
+				le32_to_cpup (&amp;td-&gt;hwNextTD));
 			if ((urb_priv-&gt;state == URB_DEL)) {
 				tdINFO = le32_to_cpup (&amp;td-&gt;hwINFO);
 				if (TD_CC_GET (tdINFO) &lt; 0xE)
@@ -882,17 +886,16 @@
 		}
 
 		ed-&gt;state &amp;= ~ED_URB_DEL;
-		tdHeadP = dma_to_td (ohci,
-			le32_to_cpup (&amp;ed-&gt;hwHeadP) &amp; 0xfffffff0);
+		tdHeadP = dma_to_td (ohci, le32_to_cpup (&amp;ed-&gt;hwHeadP));
 
 		if (tdHeadP == tdTailP) {
 			if (ed-&gt;state == ED_OPER)
 				ep_unlink (ohci, ed);
 			td_free (ohci, tdTailP);
-			ed-&gt;hwINFO = __constant_cpu_to_le32 (OHCI_ED_SKIP);
+			ed-&gt;hwINFO = ED_SKIP;
 			ed-&gt;state = ED_NEW;
 		} else
-			ed-&gt;hwINFO &amp;= ~__constant_cpu_to_le32 (OHCI_ED_SKIP);
+			ed-&gt;hwINFO &amp;= ~ED_SKIP;
 
 		switch (ed-&gt;type) {
 			case PIPE_CONTROL:
@@ -938,7 +941,7 @@
 	int		cc = 0;
 	struct urb	*urb;
 	urb_priv_t	*urb_priv;
- 	__u32		tdINFO, edHeadP, edTailP;
+ 	__u32		tdINFO;
 
  	unsigned long flags;
 
@@ -968,7 +971,7 @@
 			/*
 			 * Except for periodic transfers, both branches do
 			 * the same thing.  Periodic urbs get reissued until
-			 * they're "deleted" with usb_unlink_urb.
+			 * they're "deleted" (in SOF intr) by usb_unlink_urb.
 			 */
 			if ((ed-&gt;state &amp; (ED_OPER | ED_UNLINK))
 					&amp;&amp; (urb_priv-&gt;state != URB_DEL)) {
@@ -983,13 +986,11 @@
 
   		spin_lock_irqsave (&amp;ohci-&gt;lock, flags);
   		if (ed-&gt;state != ED_NEW) { 
-  			edHeadP = le32_to_cpup (&amp;ed-&gt;hwHeadP) &amp; 0xfffffff0;
-  			edTailP = le32_to_cpup (&amp;ed-&gt;hwTailP);
-
-// FIXME:  ED_UNLINK is very fuzzy w.r.t. what the hc knows...
+  			u32 edHeadP = ed-&gt;hwHeadP;
 
 			/* unlink eds if they are not busy */
-     			if ((edHeadP == edTailP) &amp;&amp; (ed-&gt;state == ED_OPER)) 
+			edHeadP &amp;= __constant_cpu_to_le32 (ED_MASK);
+     			if ((edHeadP == ed-&gt;hwTailP) &amp;&amp; (ed-&gt;state == ED_OPER)) 
      				ep_unlink (ohci, ed);
      		}	
      		spin_unlock_irqrestore (&amp;ohci-&gt;lock, flags);
diff -Nru a/drivers/usb/hcd/ohci.h b/drivers/usb/hcd/ohci.h
--- a/drivers/usb/hcd/ohci.h	Sun Feb  3 00:53:05 2002
+++ b/drivers/usb/hcd/ohci.h	Sun Feb  3 00:53:05 2002
@@ -2,86 +2,102 @@
  * OHCI HCD (Host Controller Driver) for USB.
  * 
  * (C) Copyright 1999 Roman Weissgaerber &lt;weissg@vienna.at&gt;
- * (C) Copyright 2000-2001 David Brownell &lt;dbrownell@users.sourceforge.net&gt;
+ * (C) Copyright 2000-2002 David Brownell &lt;dbrownell@users.sourceforge.net&gt;
  * 
- * This file is licenced under GPL
+ * This file is licenced under the GPL.
  * $Id: ohci.h,v 1.5 2002/01/19 00:24:01 dbrownell Exp $
  */
  
-static const int cc_to_error [16] = { 
-
-/* map OHCI status to errno values */ 
-	/* No  Error  */               0,
-	/* CRC Error  */               -EILSEQ,
-	/* Bit Stuff  */               -EPROTO,
-	/* Data Togg  */               -EILSEQ,
-	/* Stall      */               -EPIPE,
-	/* DevNotResp */               -ETIMEDOUT,
-	/* PIDCheck   */               -EPROTO,
-	/* UnExpPID   */               -EPROTO,
-	/* DataOver   */               -EOVERFLOW,
-	/* DataUnder  */               -EREMOTEIO,
-	/* (for hw)   */               -EIO,
-	/* (for hw)   */               -EIO,
-	/* BufferOver */               -ECOMM,
-	/* BuffUnder  */               -ENOSR,
-	/* (for HCD)  */               -EALREADY,
-	/* (for HCD)  */               -EALREADY 
-};
-
-
-/* ED States */
-
+/*
+ * OHCI Endpoint Descriptor (ED) ... holds TD queue
+ * See OHCI spec, section 4.2
+ */
+struct ed {
+	/* first fields are hardware-specified, le32 */
+	__u32			hwINFO;       	/* endpoint config bitmap */
+#define ED_ISO		__constant_cpu_to_le32(1 &lt;&lt; 15)
+#define ED_SKIP		__constant_cpu_to_le32(1 &lt;&lt; 14)
+#define ED_LOWSPEED	__constant_cpu_to_le32(1 &lt;&lt; 13)
+#define ED_OUT		__constant_cpu_to_le32(0x01 &lt;&lt; 11)
+#define ED_IN		__constant_cpu_to_le32(0x10 &lt;&lt; 11)
+	__u32			hwTailP;	/* tail of TD list */
+	__u32			hwHeadP;	/* head of TD list */
+#define ED_C		__constant_cpu_to_le32(0x02)	/* toggle carry */
+#define ED_H		__constant_cpu_to_le32(0x01)	/* halted */
+	__u32			hwNextED;	/* next ED in list */
+
+	/* rest are purely for the driver's use */
+	struct ed		*ed_prev;  
+	__u8			int_period;
+	__u8			int_branch;
+	__u8			int_load; 
+	__u8			int_interval;
+	__u8			state;			// ED_{NEW,UNLINK,OPER}
 #define ED_NEW 		0x00		/* unused, no dummy td */
 #define ED_UNLINK 	0x01		/* dummy td, maybe linked to hc */
 #define ED_OPER		0x02		/* dummy td, _is_ linked to hc */
+#define ED_URB_DEL  	0x08		/* for unlinking; masked in */
 
-#define ED_URB_DEL  	0x08		/* masked in */
+	__u8			type; 
+	__u16			last_iso;
+	struct ed		*ed_rm_list;
 
-/* usb_ohci_ed */
-struct ed {
-	/* first fields are hardware-specified */
-	__u32 hwINFO;       
-	__u32 hwTailP;
-	__u32 hwHeadP;
-	__u32 hwNextED;
-
-	struct ed * ed_prev;  
-	__u8 int_period;
-	__u8 int_branch;
-	__u8 int_load; 
-	__u8 int_interval;
-	__u8 state;			// ED_{NEW,UNLINK,OPER}
-	__u8 type; 
-	__u16 last_iso;
-	struct ed * ed_rm_list;
-
-	dma_addr_t dma;
-	__u32 unused [3];
-} __attribute((aligned(16)));
+	dma_addr_t		dma;			/* addr of ED */
+} __attribute__ ((aligned(16)));
+
+#define ED_MASK	((u32)~0x0f)		/* strip hw status in low addr bits */
 
  
-/* TD info field */
-#define TD_CC       0xf0000000
+/*
+ * OHCI Transfer Descriptor (TD) ... one per transfer segment
+ * See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt)
+ * and 4.3.2 (iso)
+ */
+struct td {
+	/* first fields are hardware-specified, le32 */
+	__u32		hwINFO;		/* transfer info bitmask */
+#define TD_CC       0xf0000000			/* condition code */
 #define TD_CC_GET(td_p) ((td_p &gt;&gt;28) &amp; 0x0f)
-#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) &amp; 0x0fffffff) | (((cc) &amp; 0x0f) &lt;&lt; 28)
-#define TD_EC       0x0C000000
-#define TD_T        0x03000000
-#define TD_T_DATA0  0x02000000
-#define TD_T_DATA1  0x03000000
-#define TD_T_TOGGLE 0x00000000
-#define TD_R        0x00040000
-#define TD_DI       0x00E00000
-#define TD_DI_SET(X) (((X) &amp; 0x07)&lt;&lt; 21)
-#define TD_DP       0x00180000
-#define TD_DP_SETUP 0x00000000
-#define TD_DP_IN    0x00100000
-#define TD_DP_OUT   0x00080000
+//#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) &amp; 0x0fffffff) | (((cc) &amp; 0x0f) &lt;&lt; 28)
+#define TD_EC       0x0C000000			/* error count */
+#define TD_T        0x03000000			/* data toggle state */
+#define TD_T_DATA0  0x02000000				/* DATA0 */
+#define TD_T_DATA1  0x03000000				/* DATA1 */
+#define TD_T_TOGGLE 0x00000000				/* uses ED_C */
+#define TD_DI       0x00E00000			/* frames before interrupt */
+//#define TD_DI_SET(X) (((X) &amp; 0x07)&lt;&lt; 21)
+#define TD_DP       0x00180000			/* direction/pid */
+#define TD_DP_SETUP 0x00000000			/* SETUP pid */
+#define TD_DP_IN    0x00100000				/* IN pid */
+#define TD_DP_OUT   0x00080000				/* OUT pid */
+							/* 0x00180000 rsvd */
+#define TD_R        0x00040000			/* round: short packets OK? */
+					/* bits 0x1ffff are defined by HCD */
+#define TD_ISO	    0x00010000			/* copy of ED_ISO */
+
+  	__u32		hwCBP;		/* Current Buffer Pointer (or 0) */
+  	__u32		hwNextTD;	/* Next TD Pointer */
+  	__u32		hwBE;		/* Memory Buffer End Pointer */
+
+	/* PSW is only for ISO */
+#define MAXPSW 1		/* hardware allows 8 */
+  	__u16		hwPSW [MAXPSW];
 
-#define TD_ISO	    0x00010000
-#define TD_DEL      0x00020000
+	/* rest are purely for the driver's use */
+  	__u8		index;
+  	struct ed	*ed;
+  	struct td	*next_dl_td;
+  	struct urb	*urb;
 
-/* CC Codes */
+	dma_addr_t	td_dma;		/* addr of this TD */
+	dma_addr_t	data_dma;	/* addr of data it points to */
+} __attribute__ ((aligned(32)));	/* c/b/i need 16; only iso needs 32 */
+
+#define TD_MASK	((u32)~0x1f)		/* strip hw status in low addr bits */
+
+/*
+ * Hardware transfer status codes -- CC from td-&gt;hwINFO or td-&gt;hwPSW
+ */
 #define TD_CC_NOERROR      0x00
 #define TD_CC_CRC          0x01
 #define TD_CC_BITSTUFFING  0x02
@@ -99,57 +115,50 @@
 #define TD_NOTACCESSED     0x0F
 
 
-#define MAXPSW 1
-
-struct td {
-	/* first hardware fields are in all tds */
-	__u32		hwINFO;
-  	__u32		hwCBP;		/* Current Buffer Pointer */
-  	__u32		hwNextTD;	/* Next TD Pointer */
-  	__u32		hwBE;		/* Memory Buffer End Pointer */
-
-  	__u16		hwPSW [MAXPSW];	/* PSW is only for ISO */
-
-  	__u8		unused;
-  	__u8		index;
-  	struct ed	*ed;
-  	struct td	*next_dl_td;
-  	struct urb	*urb;
-
-	dma_addr_t	td_dma;
-	dma_addr_t	data_dma;
-	__u32		unused2 [2];
-} __attribute((aligned(32)));		/* iso needs 32 */
+/* map OHCI TD status codes (CC) to errno values */ 
+static const int cc_to_error [16] = { 
+	/* No  Error  */               0,
+	/* CRC Error  */               -EILSEQ,
+	/* Bit Stuff  */               -EPROTO,
+	/* Data Togg  */               -EILSEQ,
+	/* Stall      */               -EPIPE,
+	/* DevNotResp */               -ETIMEDOUT,
+	/* PIDCheck   */               -EPROTO,
+	/* UnExpPID   */               -EPROTO,
+	/* DataOver   */               -EOVERFLOW,
+	/* DataUnder  */               -EREMOTEIO,
+	/* (for hw)   */               -EIO,
+	/* (for hw)   */               -EIO,
+	/* BufferOver */               -ECOMM,
+	/* BuffUnder  */               -ENOSR,
+	/* (for HCD)  */               -EALREADY,
+	/* (for HCD)  */               -EALREADY 
+};
 
-#define OHCI_ED_SKIP	(1 &lt;&lt; 14)
 
 /*
  * The HCCA (Host Controller Communications Area) is a 256 byte
- * structure defined in the OHCI spec. The host controller is
+ * structure defined section 4.4.1 of the OHCI spec. The HC is
  * told the base address of it.  It must be 256-byte aligned.
  */
-#define NUM_INTS 32	/* part of the OHCI standard */
 struct ohci_hcca {
-	__u32	int_table [NUM_INTS];	/* Interrupt ED table */
+#define NUM_INTS 32
+	__u32	int_table [NUM_INTS];	/* periodic schedule */
 	__u16	frame_no;		/* current frame number */
 	__u16	pad1;			/* set to 0 on each frame_no change */
 	__u32	done_head;		/* info returned for an interrupt */
 	u8	reserved_for_hc [116];
-} __attribute((aligned(256)));
+	u8	what [4];		/* spec only identifies 252 bytes :) */
+} __attribute__ ((aligned(256)));
 
   
 /*
- * Maximum number of root hub ports.  
- */
-#define MAX_ROOT_PORTS	15	/* maximum OHCI root hub ports */
-
-/*
- * This is the structure of the OHCI controller's memory mapped I/O
- * region.  This is Memory Mapped I/O.  You must use the readl() and
- * writel() macros defined in asm/io.h to access these!!
+ * This is the structure of the OHCI controller's memory mapped I/O region.
+ * You must use readl() and writel() (in &lt;asm/io.h&gt;) to access these fields!!
+ * Layout is in section 7 (and appendix B) of the spec.
  */
 struct ohci_regs {
-	/* control and status registers */
+	/* control and status registers (section 7.1) */
 	__u32	revision;
 	__u32	control;
 	__u32	cmdstatus;
@@ -157,7 +166,7 @@
 	__u32	intrenable;
 	__u32	intrdisable;
 
-	/* memory pointers */
+	/* memory pointers (section 7.2) */
 	__u32	hcca;
 	__u32	ed_periodcurrent;
 	__u32	ed_controlhead;
@@ -166,23 +175,25 @@
 	__u32	ed_bulkcurrent;
 	__u32	donehead;
 
-	/* frame counters */
+	/* frame counters (section 7.3) */
 	__u32	fminterval;
 	__u32	fmremaining;
 	__u32	fmnumber;
 	__u32	periodicstart;
 	__u32	lsthresh;
 
-	/* Root hub ports */
+	/* Root hub ports (section 7.4) */
 	struct	ohci_roothub_regs {
 		__u32	a;
 		__u32	b;
 		__u32	status;
+#define MAX_ROOT_PORTS	15	/* maximum OHCI root hub ports (RH_A_NDP) */
 		__u32	portstatus [MAX_ROOT_PORTS];
 	} roothub;
 
-	/* and some optional registers for legacy compatibility */
-} __attribute((aligned(32)));
+	/* and optional "legacy support" registers (appendix B) at 0x0100 */
+
+} __attribute__ ((aligned(32)));
 
 
 /* OHCI CONTROL AND STATUS REGISTER MASKS */
@@ -270,9 +281,8 @@
 #define	RH_A_POTPGT	(0xff &lt;&lt; 24)		/* power on to power good time */
 
 
-/* urb */
-typedef struct urb_priv
-{
+/* hcd-private per-urb state */
+typedef struct urb_priv {
 	struct ed		*ed;
 	__u16			length;		// # tds in this request
 	__u16			td_cnt;		// tds already serviced
@@ -345,7 +355,6 @@
 	int			sleeping;
 	int			ohci_int_load [NUM_INTS];
 	u32 			hc_control;	/* copy of hc control reg */
-	struct usb_device	*dev [128];
 
 	unsigned long		flags;		/* for HC bugs */
 #define	OHCI_QUIRK_AMD756	0x01			/* erratum #4 */
</pre></body></html>