patch-2.3.6 linux/drivers/usb/ohci.c

Next file: linux/drivers/usb/ohci.h
Previous file: linux/drivers/usb/ohci-debug.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.5/linux/drivers/usb/ohci.c linux/drivers/usb/ohci.c
@@ -71,60 +71,84 @@
 
 static spinlock_t ohci_edtd_lock = SPIN_LOCK_UNLOCKED;
 
+#define FIELDS_OF_ED(e)	le32_to_cpup(&e->status), le32_to_cpup(&e->tail_td), \
+			le32_to_cpup(&e->_head_td), le32_to_cpup(&e->next_ed)
+#define FIELDS_OF_TD(t)	le32_to_cpup(&t->info), le32_to_cpup(&t->cur_buf), \
+			le32_to_cpup(&t->next_td), le32_to_cpup(&t->buf_end)
+
+static const char *cc_names[16] = {
+	"no error",
+	"CRC error",
+	"bit stuff error",
+	"data toggle mismatch",
+	"stall",
+	"device not responding",
+	"PID check failed",
+	"unexpected PID",
+	"data overrun",
+	"data underrun",
+	"reserved (10)",
+	"reserved (11)",
+	"buffer overrun",
+	"buffer underrun",
+	"not accessed (14)",
+	"not accessed"
+};
+
 /*
- * Add a TD to the end of the TD list on a given ED.  This function
- * does NOT advance the ED's tail_td pointer beyond the given TD.  To
- * add multiple TDs, call this function once for each TD.  Do not
- * "simply" update tail_td yourself... This function does more than
- * that.
- * 
- * If this ED is on the controller, you MUST set its SKIP flag before
- * calling this function.
+ * Add a chain of TDs to the end of the TD list on a given ED.
+ *
+ * This function uses the first TD of the chain as the new dummy TD
+ * for the ED, and uses the old dummy TD instead of the first TD
+ * of the chain.  The reason for this is that this makes it possible
+ * to update the TD chain without needing any locking between the
+ * CPU and the OHCI controller.
  *
- * Important!  This function needs locking and atomicity as it works
- * in parallel with the HC's DMA.  Locking ohci_edtd_lock while using
- * the function is a must.
+ * The return value is the pointer to the new first TD (the old
+ * dummy TD).
+ *
+ * Important!  This function is not re-entrant w.r.t. each ED.
+ * Locking ohci_edtd_lock while using the function is a must
+ * if there is any possibility of another CPU or an interrupt routine
+ * calling this function with the same ED.
  *
  * This function can be called by the interrupt handler.
  */
-static void ohci_add_td_to_ed(struct ohci_td *td, struct ohci_ed *ed)
+static struct ohci_td *ohci_add_td_to_ed(struct ohci_td *td,
+				struct ohci_td *last_td, struct ohci_ed *ed)
 {
-	struct ohci_td *dummy_td, *prev_td;
+	struct ohci_td *t, *dummy_td;
+	u32 new_dummy;
 
 	if (ed->tail_td == 0) {
 		printk("eek! an ED without a dummy_td\n");
+		return td;
 	}
 
-	/* The ED's tail_td is constant, always pointing to the
-	 * dummy_td.  The reason the ED never processes the dummy is
-	 * that it stops processing TDs as soon as head_td == tail_td.
-	 * When it advances to this last dummy TD it conveniently stops. */
-	dummy_td = bus_to_virt(ed->tail_td);
-
-	/* Dummy's data pointer is used to point to the previous TD */
-	if (ed_head_td(ed) != ed->tail_td) {
-		prev_td = (struct ohci_td *) dummy_td->data;
-	} else {
-		/* if the ED is empty, previous is meaningless */
-		/* We'll be inserting into the head of the list */
-		prev_td = NULL;
-	}
-
-	/* Store the new back pointer and set up this TD's next */
-	dummy_td->data = td;
-	td->next_td = ed->tail_td;
-
-	/* Store the TD pointer back to the ED */
-	td->ed = ed;
-
-	if (!prev_td) { /* No previous TD? then insert us at the head */
-		if (ed_head_td(ed) != ed->tail_td)
-			printk(KERN_DEBUG "Suspicious ED...\n");
-		set_ed_head_td(ed, virt_to_bus(td));	/* put it on the ED */
-	} else {
-		/* add the TD to the end */
-		prev_td->next_td = virt_to_bus(td);
+	/* Get a pointer to the current dummy TD. */
+	dummy_td = bus_to_virt(ed_tail_td(ed));
+
+	for (t = td; ; t = bus_to_virt(le32_to_cpup(&t->next_td))) {
+		t->ed = ed;
+		if (t == last_td)
+			break;
 	}
+
+	/* Make the last TD point back to the first, since it
+	 * will become the new dummy TD. */
+	new_dummy = cpu_to_le32(virt_to_bus(td));
+	last_td->next_td = new_dummy;
+
+	/* Copy the contents of the first TD into the dummy */
+	*dummy_td = *td;
+
+	/* Turn the first TD into a dummy */
+	make_dumb_td(td);
+
+	/* Set the HC's tail pointer to the new dummy */
+	ed->tail_td = new_dummy;
+
+	return dummy_td;	/* replacement head of chain */
 } /* ohci_add_td_to_ed() */
 
 
@@ -169,9 +193,7 @@
 
 	/* if the list is not empty, insert this ED at the front */
 	/* XXX should they go on the end? */
-	if (listhead) {
-		ed->next_ed = listhead;
-	}
+	ed->next_ed = cpu_to_le32(listhead);
 
 	/* update the hardware listhead pointer */
 	writel(virt_to_bus(ed), hw_listhead_p);
@@ -221,7 +243,7 @@
 	 * Insert this ED at the front of the list.
 	 */
 	ed->next_ed = int_ed->next_ed;
-	int_ed->next_ed = virt_to_bus(ed);
+	int_ed->next_ed = cpu_to_le32(virt_to_bus(ed));
 
 	spin_unlock_irqrestore(&ohci_edtd_lock, flags);
 
@@ -249,21 +271,21 @@
  */
 void ohci_wait_for_ed_safe(struct ohci_regs *regs, struct ohci_ed *ed, int ed_type)
 {
-	__u32 hw_listcurrent;
+	__u32 *hw_listcurrent;
 
 	/* tell the controller to skip this ED */
-	ed->status |= OHCI_ED_SKIP;
+	ed->status |= cpu_to_le32(OHCI_ED_SKIP);
 
 	switch (ed_type) {
 	case HCD_ED_CONTROL:
-		hw_listcurrent = readl(regs->ed_controlcurrent);
+		hw_listcurrent = &regs->ed_controlcurrent;
 		break;
 	case HCD_ED_BULK:
-		hw_listcurrent = readl(regs->ed_bulkcurrent);
+		hw_listcurrent = &regs->ed_bulkcurrent;
 		break;
 	case HCD_ED_ISOC:
 	case HCD_ED_INT:
-		hw_listcurrent = readl(regs->ed_periodcurrent);
+		hw_listcurrent = &regs->ed_periodcurrent;
 		break;
 	default:
 		return;
@@ -273,11 +295,11 @@
 	 * If the HC is processing this ED we need to wait until the
 	 * at least the next frame.
 	 */
-	if (virt_to_bus(ed) == hw_listcurrent) {
+	if (virt_to_bus(ed) == readl(hw_listcurrent)) {
 		DECLARE_WAITQUEUE(wait, current);
 
 #ifdef OHCI_DEBUG
-		printk("Waiting a frame for OHC to finish with ED %p\n", ed);
+		printk("Waiting a frame for OHC to finish with ED %p [%x %x %x %x]\n", ed, FIELDS_OF_ED(ed));
 #endif
 
 		add_wait_queue(&start_of_frame_wakeup, &wait);
@@ -349,7 +371,7 @@
 		/* walk the list and unlink the ED if found */
 		do {
 			prev = cur;
-			cur = bus_to_virt(cur->next_ed);
+			cur = bus_to_virt(le32_to_cpup(&cur->next_ed));
 
 			if (virt_to_bus(cur) == bus_ed) {
 				/* unlink from the list */
@@ -401,7 +423,7 @@
 		return;
 
 	/* set the "skip me bit" in this ED */
-	ed->status |= OHCI_ED_SKIP;
+	ed->status |= cpu_to_le32(OHCI_ED_SKIP);
 
 	/* XXX Assuming this list will never be circular */
 
@@ -415,7 +437,7 @@
 		/* FIXME: collapse this into a nice simple loop :) */
 		if (head_td->next_td != 0) {
 			prev_td = head_td;
-			cur_td = bus_to_virt(head_td->next_td);
+			cur_td = bus_to_virt(le32_to_cpup(&head_td->next_td));
 			for (;;) {
 				if (td == cur_td) {
 					/* remove it */
@@ -425,7 +447,7 @@
 				if (cur_td->next_td == 0)
 					break;
 				prev_td = cur_td;
-				cur_td = bus_to_virt(cur_td->next_td);
+				cur_td = bus_to_virt(le32_to_cpup(&cur_td->next_td));
 			}
 		}
 	}
@@ -437,7 +459,7 @@
 	ohci_free_td(td);
 
 	/* unset the "skip me bit" in this ED */
-	ed->status &= ~OHCI_ED_SKIP;
+	ed->status &= cpu_to_le32(~OHCI_ED_SKIP);
 
 	spin_unlock_irqrestore(&ohci_edtd_lock, flags);
 } /* ohci_remove_td_from_ed() */
@@ -465,7 +487,7 @@
 			/* zero out the TD */
 			memset(new_td, 0, sizeof(*new_td));
 			/* mark the new TDs as unaccessed */
-			new_td->info = OHCI_TD_CC_NEW;
+			new_td->info = cpu_to_le32(OHCI_TD_CC_NEW);
 			/* mark it as allocated */
 			allocate_td(new_td);
 			return new_td;
@@ -492,7 +514,7 @@
 			/* zero out the ED */
 			memset(new_ed, 0, sizeof(*new_ed));
 			/* all new EDs start with the SKIP bit set */
-			new_ed->status |= OHCI_ED_SKIP;
+			new_ed->status |= cpu_to_le32(OHCI_ED_SKIP);
 			/* mark it as allocated */
 			allocate_ed(new_ed);
 			return new_ed;
@@ -509,12 +531,21 @@
 	if (!ed)
 		return;
 
-	if (ed->tail_td == 0) {
-		printk("yikes! an ED without a dummy_td\n");
-	} else
-		ohci_free_td((struct ohci_td *)bus_to_virt(ed->tail_td));
+	if (ed_head_td(ed) != 0) {
+		struct ohci_td *td, *tail_td, *next_td;
 
-	ed->status &= ~(__u32)ED_ALLOCATED;
+		td = bus_to_virt(ed_head_td(ed));
+		tail_td = bus_to_virt(ed_tail_td(ed));
+		for (;;) {
+			next_td = bus_to_virt(le32_to_cpup(&td->next_td));
+			ohci_free_td(td);
+			if (td == tail_td)
+				break;
+			td = next_td;
+		}
+	}
+
+	ed->status &= cpu_to_le32(~(__u32)ED_ALLOCATED);
 } /* ohci_free_ed() */
 
 
@@ -527,12 +558,13 @@
 inline struct ohci_td *ohci_fill_new_td(struct ohci_td *td, int dir, int toggle, __u32 flags, void *data, __u32 len, void *dev_id, usb_device_irq completed)
 {
 	/* hardware fields */
-	td->info = OHCI_TD_CC_NEW |
-		(dir & OHCI_TD_D) |
-		(toggle & OHCI_TD_DT) |
-		flags;
-	td->cur_buf = (data == NULL) ? 0 : virt_to_bus(data);
-	td->buf_end = (len == 0) ? 0 : td->cur_buf + len - 1;
+	td->info = cpu_to_le32(OHCI_TD_CC_NEW |
+			       (dir & OHCI_TD_D) |
+			       (toggle & OHCI_TD_DT) |
+			       flags);
+	td->cur_buf = (data == NULL) ? 0 : cpu_to_le32(virt_to_bus(data));
+	td->buf_end = (len == 0) ? 0 :
+		cpu_to_le32(le32_to_cpup(&td->cur_buf) + len - 1);
 
 	/* driver fields */
 	td->data = data;
@@ -555,11 +587,13 @@
  *  not be any!).  This assumes that the ED is Allocated and will
  *  force the Allocated bit on.
  */
-struct ohci_ed *ohci_fill_ed(struct ohci_device *dev, struct ohci_ed *ed, int maxpacketsize, int lowspeed, int endp_id, int isoc_tds)
+struct ohci_ed *ohci_fill_ed(struct ohci_device *dev, struct ohci_ed *ed,
+			     int maxpacketsize, int lowspeed, int endp_id,
+			     int isoc_tds)
 {
 	struct ohci_td *dummy_td;
 
-	if (ed_head_td(ed) != ed->tail_td)
+	if (ed_head_td(ed) != ed_tail_td(ed))
 		printk("Reusing a non-empty ED %p!\n", ed);
 
 	if (!ed->tail_td) {
@@ -569,9 +603,9 @@
 			return NULL;	/* no dummy available! */
 		}
 		make_dumb_td(dummy_td);	/* flag it as a dummy */
-		ed->tail_td = virt_to_bus(dummy_td);
+		ed->tail_td = cpu_to_le32(virt_to_bus(dummy_td));
 	} else {
-		dummy_td = bus_to_virt(ed->tail_td);
+		dummy_td = bus_to_virt(ed_tail_td(ed));
 		if (!td_dummy(*dummy_td))
 			printk("ED %p's dummy %p is screwy\n", ed, dummy_td);
 	}
@@ -579,11 +613,11 @@
 	/* set the head TD to the dummy and clear the Carry & Halted bits */
 	ed->_head_td = ed->tail_td;
 
-	ed->status = \
+	ed->status = cpu_to_le32(
 		ed_set_maxpacket(maxpacketsize) |
 		ed_set_speed(lowspeed) |
 		(endp_id & 0x7ff) |
-		((isoc_tds == 0) ? OHCI_ED_F_NORM : OHCI_ED_F_ISOC);
+		((isoc_tds == 0) ? OHCI_ED_F_NORM : OHCI_ED_F_ISOC));
 	allocate_ed(ed);
 	ed->next_ed = 0;
 
@@ -611,6 +645,7 @@
 	struct ohci_device *dev = usb_to_ohci(usb);
 	struct ohci_td *td;
 	struct ohci_ed *interrupt_ed;	/* endpoint descriptor for this irq */
+	int maxps = usb_maxpacket(usb, pipe);
 
 	/* Get an ED and TD */
 	interrupt_ed = ohci_get_free_ed(dev);
@@ -630,14 +665,16 @@
 	 * Set the max packet size, device speed, endpoint number, usb
 	 * device number (function address), and type of TD.
 	 */
-	ohci_fill_ed(dev, interrupt_ed, usb_maxpacket(usb,pipe), usb_pipeslow(pipe),
-		usb_pipe_endpdev(pipe), 0 /* normal TDs */);
+	ohci_fill_ed(dev, interrupt_ed, maxps, usb_pipeslow(pipe),
+		     usb_pipe_endpdev(pipe), 0 /* normal TDs */);
 
 	/* Fill in the TD */
+	if (maxps > sizeof(dev->data))
+		maxps = sizeof(dev->data);
 	ohci_fill_new_td(td, td_set_dir_out(usb_pipeout(pipe)),
 			TOGGLE_AUTO,
 			OHCI_TD_ROUND,
-			&dev->data, DATA_BUF_LEN,
+			dev->data, maxps,
 			dev_id, handler);
 	/*
 	 * TODO: be aware of how the OHCI controller deals with DMA
@@ -647,12 +684,12 @@
 	/*
 	 *  Put the TD onto our ED and make sure its ready to run
 	 */
-	ohci_add_td_to_ed(td, interrupt_ed);
-	interrupt_ed->status &= ~OHCI_ED_SKIP;
+	td = ohci_add_td_to_ed(td, td, interrupt_ed);
+	interrupt_ed->status &= cpu_to_le32(~OHCI_ED_SKIP);
 	ohci_unhalt_ed(interrupt_ed);
 
-	/* Linus did this. see asm/system.h; scary concept... I don't
-	 * know if its needed here or not but it won't hurt. */
+	/* Make sure all the stores above get done before
+	 * the store which tells the OHCI about the new ed. */
 	wmb();
 
 	/* Assimilate the new ED into the collective */
@@ -700,7 +737,8 @@
  *
  * This function can NOT be called from an interrupt.
  */
-static int ohci_control_msg(struct usb_device *usb, unsigned int pipe, void *cmd, void *data, int len)
+static int ohci_control_msg(struct usb_device *usb, unsigned int pipe,
+			    devrequest *cmd, void *data, int len)
 {
 	struct ohci_device *dev = usb_to_ohci(usb);
 	struct ohci_ed *control_ed = ohci_get_free_ed(dev);
@@ -708,8 +746,16 @@
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	int completion_status = -1;
+	devrequest our_cmd;
 
-#ifdef OHCI_DEBUG 
+	/* byte-swap fields of cmd if necessary */
+	our_cmd = *cmd;
+	cpu_to_le16s(&our_cmd.value);
+	cpu_to_le16s(&our_cmd.index);
+	cpu_to_le16s(&our_cmd.length);
+
+#ifdef OHCI_DEBUG
+	if (MegaDebug)
 	printk(KERN_DEBUG "ohci_control_msg %p (ohci_dev: %p) pipe %x, cmd %p, data %p, len %d\n", usb, dev, pipe, cmd, data, len);
 #endif
 	if (!control_ed) {
@@ -743,12 +789,11 @@
 	 * uses a DATA0 packet.
 	 *
 	 * The setup packet contains a devrequest (usb.h) which
-	 * will always be 8 bytes long.  FIXME: the cmd parameter
-	 * should be a pointer to one of these instead of a void* !!!
+	 * will always be 8 bytes long.
 	 */
 	ohci_fill_new_td(setup_td, OHCI_TD_D_SETUP, TOGGLE_DATA0,
 			OHCI_TD_IOC_OFF,
-			cmd, 8,		/* cmd is always 8 bytes long */
+			&our_cmd, 8,	/* cmd is always 8 bytes long */
 			NULL, NULL);
 
 	/* allocate the next TD */
@@ -761,7 +806,7 @@
 	}
 
 	/* link to the next TD */
-	setup_td->next_td = virt_to_bus(data_td);
+	setup_td->next_td = cpu_to_le32(virt_to_bus(data_td));
 
 	if (len > 0) {
 
@@ -795,7 +840,7 @@
 			return -1;
 		}
 
-		data_td->next_td = virt_to_bus(status_td);
+		data_td->next_td = cpu_to_le32(virt_to_bus(status_td));
 	} else {
 		status_td = data_td; /* no data_td, use it for status */
 	}
@@ -815,13 +860,7 @@
 	 * Add the chain of 2-3 control TDs to the control ED's TD list
 	 */
 	spin_lock_irqsave(&ohci_edtd_lock, flags);
-	control_ed->status |= OHCI_ED_SKIP;
-	ohci_add_td_to_ed(setup_td, control_ed);
-	if (data_td != status_td)
-		ohci_add_td_to_ed(data_td, control_ed);
-	ohci_add_td_to_ed(status_td, control_ed);
-	control_ed->status &= ~OHCI_ED_SKIP;
-	ohci_unhalt_ed(control_ed);
+	setup_td = ohci_add_td_to_ed(setup_td, status_td, control_ed);
 	spin_unlock_irqrestore(&ohci_edtd_lock, flags);
 
 #ifdef OHCI_DEBUG
@@ -873,17 +912,28 @@
 	}
 #endif
 
-	/* clean up */
-	ohci_free_td(setup_td);
-	if (data_td != status_td)
-		ohci_free_td(data_td);
-	ohci_free_td(status_td);
 	/* remove the control ED from the HC */
 	ohci_remove_control_ed(dev->ohci, control_ed);
 	ohci_free_ed(control_ed);	 /* return it to the pool */
 
-#if 0
-	printk(KERN_DEBUG "leaving ohci_control_msg\n");
+#ifdef OHCI_DEBUG
+	if (completion_status != 0) {
+		printk(KERN_ERR "ohci_control_msg: %s on cmd %x %x %x %x %x\n",
+		       cc_names[completion_status & 0xf], cmd->requesttype,
+		       cmd->request, cmd->value, cmd->index, cmd->length);
+	} else if (!usb_pipeout(pipe)) {
+		unsigned char *q = data;
+		int i;
+		printk(KERN_DEBUG "ctrl msg %x %x %x %x %x returned:",
+		       cmd->requesttype, cmd->request, cmd->value, cmd->index,
+		       cmd->length);
+		for (i = 0; i < len; ++i) {
+			if (i % 16 == 0)
+				printk("\n" KERN_DEBUG);
+			printk(" %x", q[i]);
+		}
+		printk("\n");
+	}
 #endif
 	return completion_status;
 } /* ohci_control_msg() */
@@ -921,7 +971,7 @@
 	/* Initialize all EDs in a new device with the skip flag so that
 	 * they are ignored by the controller until set otherwise. */
 	for (idx = 0; idx < NUM_EDS; ++idx) {
-		dev->ed[idx].status |= OHCI_ED_SKIP;
+		dev->ed[idx].status = cpu_to_le32(OHCI_ED_SKIP);
 	}
 
 	/*
@@ -1221,20 +1271,20 @@
  */
 static void ohci_root_hub_events(struct ohci *ohci)
 {
-		int num = 0;
+	int num = 0;
 	struct ohci_device *root_hub=usb_to_ohci(ohci->bus->root_hub);
 	int maxport = root_hub->usb->maxchild;
 
 	if (!waitqueue_active(&ohci_configure))
 		return;
-		do {
-			__u32 *portstatus_p = &ohci->regs->roothub.portstatus[num];
-			if (readl(portstatus_p) & PORT_CSC) {
-				if (waitqueue_active(&ohci_configure))
-					wake_up(&ohci_configure);
-				return;
-			}
-		} while (++num < maxport);
+	do {
+		__u32 *portstatus_p = &ohci->regs->roothub.portstatus[num];
+		if (readl(portstatus_p) & PORT_CSC) {
+			if (waitqueue_active(&ohci_configure))
+				wake_up(&ohci_configure);
+			return;
+		}
+	} while (++num < maxport);
 	
 } /* ohci_root_hub_events() */
 
@@ -1255,16 +1305,15 @@
 	struct ohci_hcca *hcca = root_hub->hcca;
 	struct ohci_td *td_list = NULL;
 	struct ohci_td *td_rev = NULL;
-  	
-	td_list_hc = hcca->donehead & 0xfffffff0;
+
+	td_list_hc = le32_to_cpup(&hcca->donehead) & 0xfffffff0;
 	hcca->donehead = 0;
 
  	while(td_list_hc) {
 		td_list = (struct ohci_td *) bus_to_virt(td_list_hc);
 		td_list->next_dl_td = td_rev;
-			
 		td_rev = td_list;
-		td_list_hc = td_list->next_td & 0xfffffff0;
+		td_list_hc = le32_to_cpup(&td_list->next_td) & 0xfffffff0;
 	}
 
 	return td_list;
@@ -1288,28 +1337,66 @@
 
 	while (td != NULL) {
 		struct ohci_td *next_td = td->next_dl_td;
+		int cc = OHCI_TD_CC_GET(le32_to_cpup(&td->info));
 
 		if (td_dummy(*td))
 			printk("yikes! reaping a dummy TD\n");
 
 		/* FIXME: munge td->info into a future standard status format */
+
+		if (cc != 0 && ohci_ed_halted(td->ed) && td->completed == 0) {
+			/*
+			 * There was an error on this TD and the ED
+			 * is halted, and this was not the last TD
+			 * of the transaction, so there will be TDs
+			 * to clean off the ED.
+			 * (We assume that a TD with a non-NULL completed
+			 * field is the last one of a transaction.
+			 * Ultimately we should have a flag in the TD
+			 * to say that it is the last one.)
+			 */
+			struct ohci_ed *ed = td->ed;
+			struct ohci_td *tail_td = bus_to_virt(ed_tail_td(ed));
+			struct ohci_td *ntd;
+
+			ohci_free_td(td);
+			td = ntd = bus_to_virt(ed_head_td(ed));
+			while (td != tail_td) {
+				ntd = bus_to_virt(le32_to_cpup(&td->next_td));
+				if (td->completed != 0)
+					break;
+				ohci_free_td(td);
+				td = ntd;
+			}
+			/* Set the ED head past the ones we cleaned
+			   off, and clear the halted flag */
+			set_ed_head_td(ed, virt_to_bus(ntd));
+			ohci_unhalt_ed(ed);
+			/* If we didn't find a TD with a completion
+			   routine, give up */
+			if (td == tail_td) {
+				td = next_td;
+				continue;
+			}
+		}
+
 		/* Check if TD should be re-queued */
 		if ((td->completed != NULL) &&
-		    (td->completed(OHCI_TD_CC_GET(td->info), td->data, td->dev_id)))
-		{
+		    (td->completed(cc, td->data, td->dev_id))) {
 			/* Mark the TD as active again:
 			 * Set the not accessed condition code
 			 * Reset the Error count
-			 * [FIXME: report errors to the device's driver]
 			 */
-			td->info |= OHCI_TD_CC_NEW;
+			td->info |= cpu_to_le32(OHCI_TD_CC_NEW);
 			clear_td_errorcount(td);
+			/* reset the toggle field to TOGGLE_AUTO (0) */
+			td->info &= cpu_to_le32(~OHCI_TD_DT);
 
 			/* point it back to the start of the data buffer */
-			td->cur_buf = virt_to_bus(td->data);
+			td->cur_buf = cpu_to_le32(virt_to_bus(td->data));
 
 			/* insert it back on its ED */
-			ohci_add_td_to_ed(td, td->ed);
+			ohci_add_td_to_ed(td, td, td->ed);
 		} else {
 			/* return it to the pool of free TDs */
 			ohci_free_td(td);
@@ -1341,7 +1428,7 @@
 	/* make context = the interrupt status bits that we care about */
 	if (hcca->donehead != 0) {
 		context = OHCI_INTR_WDH;   /* hcca donehead needs processing */
-		if (hcca->donehead & 1) {
+		if (hcca->donehead & cpu_to_le32(1)) {
 			context |= status;  /* other status change to check */
 		}
 	} else {
@@ -1352,7 +1439,7 @@
 		}
 	}
 
-	/* Disable HC interrupts */
+	/* Disable HC interrupts */ /* why? - paulus */
 	writel(OHCI_INTR_MIE, &regs->intrdisable);
 
 	/* Process the done list */
@@ -1361,7 +1448,7 @@
 		ohci_reap_donelist(ohci);
 
 		/* reset the done queue and tell the controller */
-		hcca->donehead = 0;
+		hcca->donehead = 0;	/* XXX already done in ohci_reverse_donelist */
 		writel(OHCI_INTR_WDH, &regs->intrstatus);
 
 		context &= ~OHCI_INTR_WDH;  /* mark this as checked */
@@ -1499,7 +1586,8 @@
 	 * page as that's guaranteed to have a nice boundary.
 	 */
 	dev->hcca = (struct ohci_hcca *) __get_free_page(GFP_KERNEL);
-
+	memset(dev->hcca, 0, sizeof(struct ohci_hcca));
+ 
 	/* Tell the controller where the HCCA is */
 	writel(virt_to_bus(dev->hcca), &ohci->regs->hcca);
 
@@ -1523,11 +1611,11 @@
 	 * Initialize the ED polling "tree" (for simplicity's sake in
 	 * this driver many nodes in the tree will be identical)
 	 */
-	dev->ed[ED_INT_32].next_ed = virt_to_bus(&dev->ed[ED_INT_16]);
-	dev->ed[ED_INT_16].next_ed = virt_to_bus(&dev->ed[ED_INT_8]);
-	dev->ed[ED_INT_8].next_ed = virt_to_bus(&dev->ed[ED_INT_4]);
-	dev->ed[ED_INT_4].next_ed = virt_to_bus(&dev->ed[ED_INT_2]);
-	dev->ed[ED_INT_2].next_ed = virt_to_bus(&dev->ed[ED_INT_1]);
+	dev->ed[ED_INT_32].next_ed = cpu_to_le32(virt_to_bus(&dev->ed[ED_INT_16]));
+	dev->ed[ED_INT_16].next_ed = cpu_to_le32(virt_to_bus(&dev->ed[ED_INT_8]));
+	dev->ed[ED_INT_8].next_ed = cpu_to_le32(virt_to_bus(&dev->ed[ED_INT_4]));
+	dev->ed[ED_INT_4].next_ed = cpu_to_le32(virt_to_bus(&dev->ed[ED_INT_2]));
+	dev->ed[ED_INT_2].next_ed = cpu_to_le32(virt_to_bus(&dev->ed[ED_INT_1]));
 
 	/*
 	 * Initialize the polling table to call interrupts at the
@@ -1535,23 +1623,23 @@
 	 * placeholders.  They have their SKIP bit set and are used as
 	 * list heads to insert real EDs onto.
 	 */
-	dev->hcca->int_table[0] = virt_to_bus(&dev->ed[ED_INT_1]);
+	dev->hcca->int_table[0] = cpu_to_le32(virt_to_bus(&dev->ed[ED_INT_1]));
 	for (i = 1; i < NUM_INTS; i++) {
 		if (i & 16)
 			dev->hcca->int_table[i] =
-				virt_to_bus(&dev->ed[ED_INT_32]);
+				cpu_to_le32(virt_to_bus(&dev->ed[ED_INT_32]));
 		if (i & 8)
 			dev->hcca->int_table[i] =
-				virt_to_bus(&dev->ed[ED_INT_16]);
+				cpu_to_le32(virt_to_bus(&dev->ed[ED_INT_16]));
 		if (i & 4)
 			dev->hcca->int_table[i] =
-				virt_to_bus(&dev->ed[ED_INT_8]);
+				cpu_to_le32(virt_to_bus(&dev->ed[ED_INT_8]));
 		if (i & 2)
 			dev->hcca->int_table[i] =
-				virt_to_bus(&dev->ed[ED_INT_4]);
+				cpu_to_le32(virt_to_bus(&dev->ed[ED_INT_4]));
 		if (i & 1)
 			dev->hcca->int_table[i] =
-				virt_to_bus(&dev->ed[ED_INT_2]);
+				cpu_to_le32(virt_to_bus(&dev->ed[ED_INT_2]));
 	}
 
 	/*
@@ -1569,6 +1657,7 @@
 #if 0
 	printk(KERN_DEBUG "leaving alloc_ohci %p\n", ohci);
 #endif
+printk("alloc_ohci done\n");
 
 	return ohci;
 } /* alloc_ohci() */
@@ -1929,7 +2018,7 @@
 /*
  *  Clean up when unloading the module
  */
-void module_cleanup(void){
+void cleanup_module(void){
 #	ifdef CONFIG_APM
 	apm_unregister_callback(&handle_apm_event);
 #	endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)