/*
 * OHCI HCD (Host Controller Driver) for USB.
 * 
 * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
 * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
 * 
 * This file is licenced under the GPL.
 * $Id: ohci-q.c,v 1.8 2002/03/27 20:57:01 dbrownell Exp $
 */

static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv)
{
	int		last = urb_priv->length - 1;

	if (last >= 0) {
		int		i;
		struct td	*td = urb_priv->td [0];
#ifdef CONFIG_PCI
		int		len = td->urb->transfer_buffer_length;
		int		dir = usb_pipeout (td->urb->pipe)
					? PCI_DMA_TODEVICE
					: PCI_DMA_FROMDEVICE;

		/* unmap CTRL URB setup buffer (always td 0) */
		if (usb_pipecontrol (td->urb->pipe)) {
			pci_unmap_single (hc->hcd.pdev, 
					td->data_dma, 8, PCI_DMA_TODEVICE);
			
			/* CTRL data buffer starts at td 1 if len > 0 */
			if (len && last > 0)
				td = urb_priv->td [1]; 		
		}
		/* else:  ISOC, BULK, INTR data buffer starts at td 0 */

		/* unmap data buffer */
		if (len && td->data_dma)
			pci_unmap_single (hc->hcd.pdev,
					td->data_dma, len, dir);
#else
#	warning "assuming no buffer unmapping is needed"
#endif

		for (i = 0; i <= last; i++) {
			td = urb_priv->td [i];
			if (td)
				td_free (hc, td);
		}
	}

	kfree (urb_priv);
}

/*-------------------------------------------------------------------------*/

/*
 * URB goes back to driver, and isn't reissued.
 * It's completely gone from HC data structures.
 * PRECONDITION:  no locks held  (Giveback can call into HCD.)
 */
static void finish_urb (struct ohci_hcd *ohci, struct urb *urb)
{
	unsigned long	flags;

#ifdef DEBUG
	if (!urb->hcpriv) {
		err ("already unlinked!");
		BUG ();
	}
#endif

	urb_free_priv (ohci, urb->hcpriv);
	urb->hcpriv = NULL;

	spin_lock_irqsave (&urb->lock, flags);
	if (likely (urb->status == -EINPROGRESS))
		urb->status = 0;
	spin_unlock_irqrestore (&urb->lock, flags);

#ifdef OHCI_VERBOSE_DEBUG
	urb_print (urb, "RET", usb_pipeout (urb->pipe));
#endif
	usb_hcd_giveback_urb (&ohci->hcd, urb);
}

static void td_submit_urb (struct urb *urb);

/* Report interrupt transfer completion, maybe reissue */
static void intr_resub (struct ohci_hcd *hc, struct urb *urb)
{
	urb_priv_t	*urb_priv = urb->hcpriv;
	unsigned long	flags;

#ifdef CONFIG_PCI
// FIXME rewrite this resubmit path.  use pci_dma_sync_single()
// and requeue more cheaply, and only if needed.
// Better yet ... abolish the notion of automagic resubmission.
	pci_unmap_single (hc->hcd.pdev,
		urb_priv->td [0]->data_dma,
		urb->transfer_buffer_length,
		usb_pipeout (urb->pipe)
			? PCI_DMA_TODEVICE
			: PCI_DMA_FROMDEVICE);
#endif
	/* FIXME: MP race.  If another CPU partially unlinks
	 * this URB (urb->status was updated, hasn't yet told
	 * us to dequeue) before we call complete() here, an
	 * extra "unlinked" completion will be reported...
	 */

	spin_lock_irqsave (&urb->lock, flags);
	if (likely (urb->status == -EINPROGRESS))
		urb->status = 0;
	spin_unlock_irqrestore (&urb->lock, flags);

#ifdef OHCI_VERBOSE_DEBUG
	urb_print (urb, "INTR", usb_pipeout (urb->pipe));
#endif
	urb->complete (urb);

	/* always requeued, but ED_SKIP if complete() unlinks.
	 * EDs are removed from periodic table only at SOF intr.
	 */
	urb->actual_length = 0;
	spin_lock_irqsave (&urb->lock, flags);
	if (urb_priv->state != URB_DEL)
		urb->status = -EINPROGRESS;
	spin_unlock (&urb->lock);

	spin_lock (&hc->lock);
	td_submit_urb (urb);
	spin_unlock_irqrestore (&hc->lock, flags);
}


/*-------------------------------------------------------------------------*
 * ED handling functions
 *-------------------------------------------------------------------------*/  

/* search for the right branch to insert an interrupt ed into the int tree 
 * do some load balancing;
 * returns the branch and 
 * sets the interval to interval = 2^integer (ld (interval))
 */
static int ep_int_balance (struct ohci_hcd *ohci, int interval, int load)
{
	int	i, branch = 0;

	/* search for the least loaded interrupt endpoint branch */
	for (i = 0; i < NUM_INTS ; i++) 
		if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i])
			branch = i; 

	branch = branch % interval;
	for (i = branch; i < NUM_INTS; i += interval)
		ohci->ohci_int_load [i] += load;

	return branch;
}

/*-------------------------------------------------------------------------*/

/*  2^int ( ld (inter)) */

static int ep_2_n_interval (int inter)
{	
	int	i;

	for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++)
		continue;
	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)
{
	int			i, wout = 0;

	for (i = 0; i < num_bits; i++)
		wout |= (( (word >> i) & 1) << (num_bits - i - 1));
	return wout;
}

/*-------------------------------------------------------------------------*/

/* link an ed into one of the HC chains */

static int ep_link (struct ohci_hcd *ohci, struct ed *edi)
{	 
	int			int_branch, i;
	int			inter, interval, load;
	__u32			*ed_p;
	volatile struct ed	*ed = edi;

	ed->state = ED_OPER;

	switch (ed->type) {
	case PIPE_CONTROL:
		ed->hwNextED = 0;
		if (ohci->ed_controltail == NULL) {
			writel (ed->dma, &ohci->regs->ed_controlhead);
		} else {
			ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma);
		}
		ed->ed_prev = ohci->ed_controltail;
		if (!ohci->ed_controltail
				&& !ohci->ed_rm_list
				&& !ohci->sleeping
				) {
			ohci->hc_control |= OHCI_CTRL_CLE;
			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->dma, &ohci->regs->ed_bulkhead);
		} else {
			ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma);
		}
		ed->ed_prev = ohci->ed_bulktail;
		if (!ohci->ed_bulktail
				&& !ohci->ed_rm_list
				&& !ohci->sleeping
				) {
			ohci->hc_control |= OHCI_CTRL_BLE;
			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);
		ed->interval = interval;
		int_branch = ep_int_balance (ohci, interval, load);
		ed->int_branch = int_branch;

		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) && ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->interval >= interval); 
				ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) 
					inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->interval);
			ed->hwNextED = *ed_p; 
			*ed_p = cpu_to_le32 (ed->dma);
		}
#ifdef OHCI_VERBOSE_DEBUG
		ohci_dump_periodic (ohci, "LINK_INT");
#endif
		break;

	case PIPE_ISOCHRONOUS:
		ed->hwNextED = 0;
		ed->interval = 1;
		if (ohci->ed_isotail != NULL) {
			ohci->ed_isotail->hwNextED = cpu_to_le32 (ed->dma);
			ed->ed_prev = ohci->ed_isotail;
		} else {
			for ( i = 0; i < NUM_INTS; i += inter) {
				inter = 1;
				for (ed_p = & (ohci->hcca->int_table [ep_rev (5, i)]); 
					*ed_p != 0; 
					ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) 
						inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->interval);
				*ed_p = cpu_to_le32 (ed->dma);	
			}	
			ed->ed_prev = NULL;
		}	
		ohci->ed_isotail = edi;  
#ifdef OHCI_VERBOSE_DEBUG
		ohci_dump_periodic (ohci, "LINK_ISO");
#endif
		break;
	}	 	
	return 0;
}

/*-------------------------------------------------------------------------*/

/* scan the periodic table to find and unlink this ED */
static void periodic_unlink (
	struct ohci_hcd	*ohci,
	struct ed	*ed,
	unsigned	index,
	unsigned	period
) {
	for (; index < NUM_INTS; index += period) {
		__u32	*ed_p = &ohci->hcca->int_table [index];

		while (*ed_p != 0) {
			if ((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) {
				*ed_p = ed->hwNextED;		
				break;
			}
			ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED);
		}
	}	
}

/* unlink an ed from one of the HC chains. 
 * just the link to the ed is unlinked.
 * 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 start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed) 
{
	int	i;

	ed->hwINFO |= 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 (le32_to_cpup (&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 {
			 (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))
			 	->ed_prev = ed->ed_prev;
		}
		break;

	case PIPE_BULK:
		if (ed->ed_prev == NULL) {
			if (!ed->hwNextED) {
				ohci->hc_control &= ~OHCI_CTRL_BLE;
				writel (ohci->hc_control, &ohci->regs->control);
			}
			writel (le32_to_cpup (&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 {
			 (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))
			 	->ed_prev = ed->ed_prev;
		}
		break;

	case PIPE_INTERRUPT:
		periodic_unlink (ohci, ed, ed->int_branch, ed->interval);
		for (i = ed->int_branch; i < NUM_INTS; i += ed->interval)
			ohci->ohci_int_load [i] -= ed->int_load;
#ifdef OHCI_VERBOSE_DEBUG
		ohci_dump_periodic (ohci, "UNLINK_INT");
#endif
		break;

	case PIPE_ISOCHRONOUS:
		if (ohci->ed_isotail == ed)
			ohci->ed_isotail = ed->ed_prev;
		if (ed->hwNextED != 0) 
			(dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))
		    		->ed_prev = ed->ed_prev;

		if (ed->ed_prev != NULL)
			ed->ed_prev->hwNextED = ed->hwNextED;
		else
			periodic_unlink (ohci, ed, 0, 1);
#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).
	 * - use ed_rm_list and finish_unlinks(), adding some state that
	 *   prevents clobbering hw linkage before the appropriate SOF
	 * - a speedup:  when only one urb is queued on the ed, save 1msec
	 *   by making start_urb_unlink() use this routine to deschedule.
	 */
	ed->state = ED_UNLINK;
	return 0;
}


/*-------------------------------------------------------------------------*/

/* (re)init an endpoint; this _should_ be done once at the
 * usb_set_configuration command, but the USB stack is a bit stateless
 * so we do it at every transaction.
 * if the state of the ed is ED_NEW then a dummy td is added and the
 * state is changed to ED_UNLINK
 * in all other cases the state is left unchanged
 * the ed info fields are set even though most of them should
 * not change
 */
static struct ed *ep_add_ed (
	struct usb_device	*udev,
	unsigned int		pipe,
	int			interval,
	int			load,
	int			mem_flags
) {
   	struct ohci_hcd		*ohci = hcd_to_ohci (udev->bus->hcpriv);
	struct hcd_dev		*dev = (struct hcd_dev *) udev->hcpriv;
	struct td		*td;
	struct ed		*ed; 
	unsigned		ep;
	unsigned long		flags;

	spin_lock_irqsave (&ohci->lock, flags);

	ep = usb_pipeendpoint (pipe) << 1;
	if (!usb_pipecontrol (pipe) && usb_pipeout (pipe))
		ep |= 1;
	if (!(ed = dev->ep [ep])) {
		ed = ed_alloc (ohci, SLAB_ATOMIC);
		if (!ed) {
			/* out of memory */
			spin_unlock_irqrestore (&ohci->lock, flags);
			return NULL;
		}
		dev->ep [ep] = ed;
	}

	if (ed->state & ED_URB_DEL) {
		/* pending unlink request */
		spin_unlock_irqrestore (&ohci->lock, flags);
		return NULL;
	}

	if (ed->state == ED_NEW) {
		ed->hwINFO = ED_SKIP;
  		/* dummy td; end of td list for ed */
		td = td_alloc (ohci, SLAB_ATOMIC);
 		if (!td) {
			/* out of memory */
			spin_unlock_irqrestore (&ohci->lock, flags);
			return NULL;
		}
		ed->hwTailP = cpu_to_le32 (td->td_dma);
		ed->hwHeadP = ed->hwTailP;	
		ed->state = ED_UNLINK;
		ed->type = usb_pipetype (pipe);
	}

// FIXME:  don't do this if it's linked to the HC,
// we might clobber data toggle or other state ...

	ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe)
			| usb_pipeendpoint (pipe) << 7
			| (usb_pipeisoc (pipe)? 0x8000: 0)
			| (usb_pipecontrol (pipe)
				? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) 
			| (udev->speed == USB_SPEED_LOW) << 13
			| usb_maxpacket (udev, pipe, usb_pipeout (pipe))
				<< 16);

  	if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) {
  		ed->int_period = interval;
  		ed->int_load = load;
  	}

	spin_unlock_irqrestore (&ohci->lock, flags);
	return ed; 
}

/*-------------------------------------------------------------------------*/

/* request unlinking of an endpoint from an operational HC.
 * put the ep on the rm_list and stop the bulk or ctrl list 
 * real work is done at the next start frame (SF) hardware interrupt
 */
static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed)
{    
	/* already pending? */
	if (ed->state & ED_URB_DEL)
		return;
	ed->state |= ED_URB_DEL;

	ed->hwINFO |= ED_SKIP;

	switch (ed->type) {
		case PIPE_CONTROL: /* stop control list */
			ohci->hc_control &= ~OHCI_CTRL_CLE;
			writel (ohci->hc_control,
				&ohci->regs->control); 
			break;
		case PIPE_BULK: /* stop bulk list */
			ohci->hc_control &= ~OHCI_CTRL_BLE;
			writel (ohci->hc_control,
				&ohci->regs->control); 
			break;
	}

	/* SF interrupt might get delayed; record the frame counter value that
	 * indicates when the HC isn't looking at it, so concurrent unlinks
	 * behave.  frame_no wraps every 2^16 msec, and changes right before
	 * SF is triggered.
	 */
	ed->tick = le16_to_cpu (ohci->hcca->frame_no) + 1;

	ed->ed_rm_list = ohci->ed_rm_list;
	ohci->ed_rm_list = ed;

	/* enable SOF interrupt */
	if (!ohci->sleeping) {
		writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
		writel (OHCI_INTR_SF, &ohci->regs->intrenable);
	}
}

/*-------------------------------------------------------------------------*
 * TD handling functions
 *-------------------------------------------------------------------------*/

/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */

static void
td_fill (struct ohci_hcd *ohci, unsigned int info,
	dma_addr_t data, int len,
	struct urb *urb, int index)
{
	volatile struct td	*td, *td_pt;
	urb_priv_t		*urb_priv = urb->hcpriv;

	if (index >= urb_priv->length) {
		err ("internal OHCI error: TD index > length");
		return;
	}

#if 0
	/* no interrupt needed except for URB's last TD */
	if (index != (urb_priv->length - 1))
		info |= TD_DI;
#endif

	/* use this td as the next dummy */
	td_pt = urb_priv->td [index];
	td_pt->hwNextTD = 0;

	/* fill the old dummy TD */
	td = urb_priv->td [index] = dma_to_td (ohci,
			le32_to_cpup (&urb_priv->ed->hwTailP));

	td->ed = urb_priv->ed;
	td->next_dl_td = NULL;
	td->index = index;
	td->urb = urb; 
	td->data_dma = data;
	if (!len)
		data = 0;

	td->hwINFO = cpu_to_le32 (info);
	if ((td->ed->type) == PIPE_ISOCHRONOUS) {
		td->hwCBP = cpu_to_le32 (data & 0xFFFFF000);
		td->ed->last_iso = info & 0xffff;
	} else {
		td->hwCBP = cpu_to_le32 (data); 
	}			
	if (data)
		td->hwBE = cpu_to_le32 (data + len - 1);
	else
		td->hwBE = 0;
	td->hwNextTD = cpu_to_le32 (td_pt->td_dma);
	td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000);

	/* HC might read the TD right after we link it ... */
	wmb ();

	/* append to queue */
	td->ed->hwTailP = td->hwNextTD;
}

/*-------------------------------------------------------------------------*/

/* prepare all TDs of a transfer */

static void td_submit_urb (struct urb *urb)
{ 
	urb_priv_t	*urb_priv = urb->hcpriv;
	struct ohci_hcd *ohci = hcd_to_ohci (urb->dev->bus->hcpriv);
	dma_addr_t	data;
	int		data_len = urb->transfer_buffer_length;
	int		cnt = 0; 
	__u32		info = 0;
  	unsigned int	toggle = 0;

	/* OHCI handles the DATA-toggles itself, we just use the
	 * USB-toggle bits for resetting
	 */
  	if (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
			usb_pipeout (urb->pipe))) {
  		toggle = TD_T_TOGGLE;
	} else {
  		toggle = TD_T_DATA0;
		usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe),
			usb_pipeout (urb->pipe), 1);
	}

	urb_priv->td_cnt = 0;

	if (data_len) {
#ifdef CONFIG_PCI
		data = pci_map_single (ohci->hcd.pdev,
			urb->transfer_buffer, data_len,
			usb_pipeout (urb->pipe)
				? PCI_DMA_TODEVICE
				: PCI_DMA_FROMDEVICE
			);
#else
#	error "what dma addr to use"
#endif
	} else
		data = 0;

	/* NOTE:  TD_CC is set so we can tell which TDs the HC processed by
	 * using TD_CC_GET, as well as by seeing them on the done list.
	 */
	switch (usb_pipetype (urb->pipe)) {
		case PIPE_BULK:
			info = usb_pipeout (urb->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, urb, cnt);
				data += 4096; data_len -= 4096; cnt++;
			}
			info = usb_pipeout (urb->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, urb, cnt);
			cnt++;
			if ((urb->transfer_flags & USB_ZERO_PACKET)
					&& cnt < urb_priv->length) {
				td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle),
					0, 0, urb, cnt);
				cnt++;
			}
			/* start bulk list */
			if (!ohci->sleeping) {
				wmb ();
				writel (OHCI_BLF, &ohci->regs->cmdstatus);
			}
			break;

		case PIPE_INTERRUPT:
			info = TD_CC | toggle;
			info |= usb_pipeout (urb->pipe) 
				?  TD_DP_OUT
				:  TD_R | TD_DP_IN;
			td_fill (ohci, info, data, data_len, urb, cnt++);
			break;

		case PIPE_CONTROL:
			/* control requests don't use toggle state  */
			info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
			td_fill (ohci, info,
#ifdef CONFIG_PCI
				pci_map_single (ohci->hcd.pdev,
					urb->setup_packet, 8,
					PCI_DMA_TODEVICE),
#else
#	error "what dma addr to use"				
#endif
				8, urb, cnt++); 
			if (data_len > 0) {  
				info = TD_CC | TD_R | TD_T_DATA1;
				info |= usb_pipeout (urb->pipe)
				    ? TD_DP_OUT
				    : TD_DP_IN;
				/* NOTE:  mishandles transfers >8K, some >4K */
				td_fill (ohci, info, data, data_len,
						urb, cnt++);  
			} 
			info = usb_pipeout (urb->pipe)
				? TD_CC | TD_DP_IN | TD_T_DATA1
				: TD_CC | TD_DP_OUT | TD_T_DATA1;
			td_fill (ohci, info, data, 0, urb, cnt++);
			/* start control list */
			if (!ohci->sleeping) {
				wmb ();
				writel (OHCI_CLF, &ohci->regs->cmdstatus);
			}
			break;

		case PIPE_ISOCHRONOUS:
			for (cnt = 0; cnt < urb->number_of_packets; cnt++) {
				int	frame = urb->start_frame;

				// FIXME scheduling should handle frame counter
				// roll-around ... exotic case (and OHCI has
				// a 2^16 iso range, vs other HCs max of 2^10)
				frame += cnt * urb->interval;
				frame &= 0xffff;
				td_fill (ohci, TD_CC | TD_ISO | frame,
				    data + urb->iso_frame_desc [cnt].offset, 
				    urb->iso_frame_desc [cnt].length, urb, cnt); 
			}
			break;
	} 
	if (urb_priv->length != cnt) 
		dbg ("TD LENGTH %d != CNT %d", urb_priv->length, cnt);
}

/*-------------------------------------------------------------------------*
 * Done List handling functions
 *-------------------------------------------------------------------------*/

/* calculate transfer length/status and update the urb
 * PRECONDITION:  irqsafe (only for urb->status locking)
 */
static void td_done (struct urb *urb, struct td *td)
{
	u32	tdINFO = le32_to_cpup (&td->hwINFO);
	int	cc = 0;


	/* ISO ... drivers see per-TD length/status */
  	if (tdINFO & TD_ISO) {
 		u16	tdPSW = le16_to_cpu (td->hwPSW [0]);
		int	dlen = 0;

 		cc = (tdPSW >> 12) & 0xF;
		if (! ((urb->transfer_flags & USB_DISABLE_SPD)
				&& (cc == TD_DATAUNDERRUN)))
			cc = TD_CC_NOERROR;

		if (usb_pipeout (urb->pipe))
			dlen = urb->iso_frame_desc [td->index].length;
		else
			dlen = tdPSW & 0x3ff;
		urb->actual_length += dlen;
		urb->iso_frame_desc [td->index].actual_length = dlen;
		urb->iso_frame_desc [td->index].status = cc_to_error [cc];

		if (cc != 0)
			dbg ("  urb %p iso TD %d len %d CC %d",
				urb, td->index, dlen, cc);

	/* BULK, INT, CONTROL ... drivers see aggregate length/status,
	 * except that "setup" bytes aren't counted and "short" transfers
	 * might not be reported as errors.
	 */
	} else {
		int	type = usb_pipetype (urb->pipe);
		u32	tdBE = le32_to_cpup (&td->hwBE);

  		cc = TD_CC_GET (tdINFO);

		/* control endpoints only have soft stalls */
  		if (type != PIPE_CONTROL && cc == TD_CC_STALL)
			usb_endpoint_halt (urb->dev,
				usb_pipeendpoint (urb->pipe),
				usb_pipeout (urb->pipe));

		/* update packet status if needed (short may be ok) */
		if (((urb->transfer_flags & USB_DISABLE_SPD) != 0
				&& cc == TD_DATAUNDERRUN))
			cc = TD_CC_NOERROR;
		if (cc != TD_CC_NOERROR) {
			spin_lock (&urb->lock);
			if (urb->status == -EINPROGRESS)
				urb->status = cc_to_error [cc];
			spin_unlock (&urb->lock);
		}

		/* count all non-empty packets except control SETUP packet */
		if ((type != PIPE_CONTROL || td->index != 0) && tdBE != 0) {
			if (td->hwCBP == 0)
				urb->actual_length += tdBE - td->data_dma + 1;
			else
				urb->actual_length +=
					  le32_to_cpup (&td->hwCBP)
					- td->data_dma;
		}

		if (cc != 0)
			dbg ("  urb %p TD %d CC %d, len=%d",
				urb, td->index, cc, urb->actual_length);
  	}
}

/*-------------------------------------------------------------------------*/

/* replies to the request have to be on a FIFO basis so
 * we unreverse the hc-reversed done-list
 */
static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
{
	__u32		td_list_hc;
	struct td	*td_rev = NULL;
	struct td	*td_list = NULL;
  	urb_priv_t	*urb_priv = NULL;
  	unsigned long	flags;

  	spin_lock_irqsave (&ohci->lock, flags);

	td_list_hc = le32_to_cpup (&ohci->hcca->done_head);
	ohci->hcca->done_head = 0;

	while (td_list_hc) {		
		td_list = dma_to_td (ohci, td_list_hc);

		if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) {
			urb_priv = (urb_priv_t *) td_list->urb->hcpriv;
			/* typically the endpoint halts on error; un-halt,
			 * and maybe dequeue other TDs from this urb
			 */
			if (td_list->ed->hwHeadP & ED_H) {
				if (urb_priv && ((td_list->index + 1)
						< urb_priv->length)) {
#ifdef OHCI_VERBOSE_DEBUG
					dbg ("urb %p TD %d of %d, patch ED",
						td_list->urb,
						1 + td_list->index,
						urb_priv->length);
#endif
					td_list->ed->hwHeadP = 
			    (urb_priv->td [urb_priv->length - 1]->hwNextTD
				    & __constant_cpu_to_le32 (TD_MASK))
			    | (td_list->ed->hwHeadP & ED_C);
					urb_priv->td_cnt += urb_priv->length
						- td_list->index - 1;
				} else 
					td_list->ed->hwHeadP &= ~ED_H;
			}
		}

		td_list->next_dl_td = td_rev;	
		td_rev = td_list;
		td_list_hc = le32_to_cpup (&td_list->hwNextTD);
	}	
	spin_unlock_irqrestore (&ohci->lock, flags);
	return td_list;
}

/*-------------------------------------------------------------------------*/

/* wrap-aware logic stolen from <linux/jiffies.h> */
#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0)

/* there are some urbs/eds to unlink; called in_irq(), with HCD locked */
static void finish_unlinks (struct ohci_hcd *ohci, u16 tick)
{
	struct ed	*ed, **last;
	int		ctrl = 0, bulk = 0;

	for (last = &ohci->ed_rm_list, ed = *last; ed != NULL; ed = *last) {
		struct td	*td, *td_next, *tdHeadP, *tdTailP;
		u32		*td_p;
		int		unlinked;

		/* only take off EDs that the HC isn't using, accounting for
		 * frame counter wraps.  completion callbacks might prepend
		 * EDs to the list, they'll be checked next irq.
		 */
		if (tick_before (tick, ed->tick)) {
			last = &ed->ed_rm_list;
			continue;
		}
		*last = ed->ed_rm_list;
		ed->ed_rm_list = 0;
		unlinked = 0;

		/* unlink urbs from first one requested to queue end;
		 * leave earlier urbs alone
		 */
		tdTailP = dma_to_td (ohci, le32_to_cpup (&ed->hwTailP));
		tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP));
		td_p = &ed->hwHeadP;

		for (td = tdHeadP; td != tdTailP; td = td_next) {
			struct urb *urb = td->urb;
			urb_priv_t *urb_priv = td->urb->hcpriv;

			td_next = dma_to_td (ohci,
				le32_to_cpup (&td->hwNextTD));
			if (unlinked || (urb_priv->state == URB_DEL)) {
				u32 tdINFO = le32_to_cpup (&td->hwINFO);

				unlinked = 1;

				/* HC may have partly processed this TD */
				if (TD_CC_GET (tdINFO) < 0xE)
					td_done (urb, td);
				*td_p = td->hwNextTD | (*td_p
					& __constant_cpu_to_le32 (0x3));

				/* URB is done; clean up */
				if (++ (urb_priv->td_cnt) == urb_priv->length) {
					if (urb->status == -EINPROGRESS)
						urb->status = -ECONNRESET;
     					spin_unlock (&ohci->lock);
					finish_urb (ohci, urb);
					spin_lock (&ohci->lock);
				}
			} else {
				td_p = &td->hwNextTD;
			}
		}

		/* FIXME actually want four cases here:
		 * (a) finishing URB unlink
		 *     [a1] no URBs queued, so start ED unlink
		 *     [a2] some (earlier) URBs still linked, re-enable
		 * (b) finishing ED unlink
		 *     [b1] no URBs queued, ED is truly idle now
		 *     [b2] URBs now queued, link ED back into schedule
		 * right now we only have (a)
		 */
		ed->state &= ~ED_URB_DEL;
		tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP));

		if (tdHeadP == tdTailP) {
			if (ed->state == ED_OPER)
				start_ed_unlink (ohci, ed);
			td_free (ohci, tdTailP);
			ed->hwINFO = ED_SKIP;
			ed->state = ED_NEW;
		} else
			ed->hwINFO &= ~ED_SKIP;

		switch (ed->type) {
			case PIPE_CONTROL:
				ctrl = 1;
				break;
			case PIPE_BULK:
				bulk = 1;
				break;
		}
   	}

	/* maybe reenable control and bulk lists */ 
	if (!ohci->disabled) {
		if (ctrl) 	/* reset control list */
			writel (0, &ohci->regs->ed_controlcurrent);
		if (bulk)	/* reset bulk list */
			writel (0, &ohci->regs->ed_bulkcurrent);
		if (!ohci->ed_rm_list) {
			if (ohci->ed_controltail)
				ohci->hc_control |= OHCI_CTRL_CLE;
			if (ohci->ed_bulktail)
				ohci->hc_control |= OHCI_CTRL_BLE;
			writel (ohci->hc_control, &ohci->regs->control);   
		}
	}
}



/*-------------------------------------------------------------------------*/

/*
 * Process normal completions (error or success) and clean the schedules.
 *
 * This is the main path for handing urbs back to drivers.  The only other
 * path is finish_unlinks(), which unlinks URBs using ed_rm_list, instead of
 * scanning the (re-reversed) donelist as this does.
 */
static void dl_done_list (struct ohci_hcd *ohci, struct td *td)
{
	unsigned long	flags;

  	spin_lock_irqsave (&ohci->lock, flags);
  	while (td) {
		struct td	*td_next = td->next_dl_td;
		struct urb	*urb = td->urb;
		urb_priv_t	*urb_priv = urb->hcpriv;
		struct ed	*ed = td->ed;

		/* update URB's length and status from TD */
   		td_done (urb, td);
  		urb_priv->td_cnt++;

		/* If all this urb's TDs are done, call complete().
		 * Interrupt transfers are the only special case:
		 * they're reissued, until "deleted" by usb_unlink_urb
		 * (real work done in a SOF intr, by finish_unlinks).
		 */
  		if (urb_priv->td_cnt == urb_priv->length) {
			int	resubmit;

			resubmit = usb_pipeint (urb->pipe)
					&& (urb_priv->state != URB_DEL);

     			spin_unlock_irqrestore (&ohci->lock, flags);
			if (resubmit)
  				intr_resub (ohci, urb);
  			else
  				finish_urb (ohci, urb);
  			spin_lock_irqsave (&ohci->lock, flags);
  		}

		/* clean schedule:  unlink EDs that are no longer busy */
		if ((ed->hwHeadP & __constant_cpu_to_le32 (TD_MASK))
					== ed->hwTailP
				&& (ed->state == ED_OPER)) 
			start_ed_unlink (ohci, ed);
    		td = td_next;
  	}  
	spin_unlock_irqrestore (&ohci->lock, flags);
}