⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ohci-hcd.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if ((ohci->hcca->done_head != 0)			&& ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {		ints =  OHCI_INTR_WDH;	} else if ((ints = (readl (&regs->intrstatus)			& readl (&regs->intrenable))) == 0) {		return;	} 	// dbg ("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));	if (ints & OHCI_INTR_UE) {		ohci->disabled++;		err ("OHCI Unrecoverable Error, %s disabled", hcd->self.bus_name);		// e.g. due to PCI Master/Target Abort#ifdef	DEBUG		ohci_dump (ohci, 1);#endif		hc_reset (ohci);	}  	if (ints & OHCI_INTR_WDH) {		writel (OHCI_INTR_WDH, &regs->intrdisable);			dl_done_list (ohci, dl_reverse_done_list (ohci));		writel (OHCI_INTR_WDH, &regs->intrenable); 	}  	/* could track INTR_SO to reduce available PCI/... bandwidth */	// FIXME:  this assumes SOF (1/ms) interrupts don't get lost...	if (ints & OHCI_INTR_SF) { 		unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1;		writel (OHCI_INTR_SF, &regs->intrdisable);			if (ohci->ed_rm_list [!frame] != NULL) {			dl_del_list (ohci, !frame);		}		if (ohci->ed_rm_list [frame] != NULL)			writel (OHCI_INTR_SF, &regs->intrenable);		}	writel (ints, &regs->intrstatus);	writel (OHCI_INTR_MIE, &regs->intrenable);	}/*-------------------------------------------------------------------------*/static void ohci_stop (struct usb_hcd *hcd){		struct ohci_hcd		*ohci = hcd_to_ohci (hcd);	dbg ("%s: stop %s controller%s",		hcd->self.bus_name,		hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),		ohci->disabled ? " (disabled)" : ""		);#ifdef	DEBUG	ohci_dump (ohci, 1);#endif	if (!ohci->disabled)		hc_reset (ohci);		ohci_mem_cleanup (ohci);#ifdef CONFIG_PCI	pci_free_consistent (ohci->hcd.pdev, sizeof *ohci->hcca,		ohci->hcca, ohci->hcca_dma);#endif}/*-------------------------------------------------------------------------*/static int __devinitohci_start (struct usb_hcd *hcd){	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);	int		ret;#ifdef CONFIG_PCI	if (hcd->pdev) {		ohci->hcca = pci_alloc_consistent (hcd->pdev,				sizeof *ohci->hcca, &ohci->hcca_dma);		if (!ohci->hcca)			return -ENOMEM;		/* AMD 756, for most chips (early revs), corrupts register		 * values on read ... so enable the vendor workaround.		 */		if (hcd->pdev->vendor == 0x1022				&& hcd->pdev->device == 0x740c) {			ohci->flags = OHCI_QUIRK_AMD756;			info ("%s: AMD756 erratum 4 workaround",				hcd->self.bus_name);		}		/* Apple's OHCI driver has a lot of bizarre workarounds		 * for this chip.  Evidently control and bulk lists		 * can get confused.  (B&W G3 models, and ...)		 */		else if (hcd->pdev->vendor == 0x1045				&& hcd->pdev->device == 0xc861) {			info ("%s: WARNING: OPTi workarounds unavailable",				hcd->self.bus_name);		}	}#else#	error "where's hcca coming from?"#endif /* CONFIG_PCI */        memset (ohci->hcca, 0, sizeof (struct ohci_hcca));	if ((ret = ohci_mem_init (ohci)) < 0) {		ohci_stop (hcd);		return ret;	}	ohci->regs = hcd->regs;	if (hc_reset (ohci) < 0) {		ohci_stop (hcd);		return -ENODEV;	}	if (hc_start (ohci) < 0) {		err ("can't start %s", ohci->hcd.self.bus_name);		ohci_stop (hcd);		return -EBUSY;	}#ifdef	DEBUG	ohci_dump (ohci, 1);#endif	return 0;}/*-------------------------------------------------------------------------*/#ifdef	CONFIG_PMstatic int ohci_suspend (struct usb_hcd *hcd, u32 state){	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);	unsigned long		flags;	u16			cmd;	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {		dbg ("can't suspend %s (state is %s)", hcd->self.bus_name,			hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));		return -EIO;	}	/* act as if usb suspend can always be used */	dbg ("%s: suspend to %d", hcd->self.bus_name, state);	ohci->sleeping = 1;	/* First stop processing */  	spin_lock_irqsave (&ohci->lock, flags);	ohci->hc_control &=		~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);	writel (ohci->hc_control, &ohci->regs->control);	writel (OHCI_INTR_SF, &ohci->regs->intrstatus);	(void) readl (&ohci->regs->intrstatus);  	spin_unlock_irqrestore (&ohci->lock, flags);	/* Wait a frame or two */	mdelay (1);	if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)		mdelay (1);		 #ifdef CONFIG_PMAC_PBOOK	if (_machine == _MACH_Pmac)		disable_irq (hcd->pdev->irq); 	/* else, 2.4 assumes shared irqs -- don't disable */ #endif	/* Enable remote wakeup */	writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD,		&ohci->regs->intrenable);	/* Suspend chip and let things settle down a bit */ 	ohci->hc_control = OHCI_USB_SUSPEND; 	writel (ohci->hc_control, &ohci->regs->control);	(void) readl (&ohci->regs->control);	mdelay (500); /* No schedule here ! */	switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {		case OHCI_USB_RESET:			dbg ("%s suspend->reset ?", hcd->self.bus_name);			break;		case OHCI_USB_RESUME:			dbg ("%s suspend->resume ?", hcd->self.bus_name);			break;		case OHCI_USB_OPER:			dbg ("%s suspend->operational ?", hcd->self.bus_name);			break;		case OHCI_USB_SUSPEND:			dbg ("%s suspended", hcd->self.bus_name);			break;	}	/* In some rare situations, Apple's OHCI have happily trashed	 * memory during sleep. We disable its bus master bit during	 * suspend	 */	pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd);	cmd &= ~PCI_COMMAND_MASTER;	pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd);#ifdef CONFIG_PMAC_PBOOK	{	   	struct device_node	*of_node; 		/* Disable USB PAD & cell clock */		of_node = pci_device_to_OF_node (hcd->pdev);		if (of_node)			pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);	}#endif	return 0;}// FIXME:  this restart logic should be generic,// and handle full hcd state cleanup/* controller died; cleanup debris, then restart *//* must not be called from interrupt context */static int hc_restart (struct ohci_hcd *ohci){	int temp;	int i;	ohci->disabled = 1;	ohci->sleeping = 0;	if (ohci->hcd.self.root_hub)		usb_disconnect (&ohci->hcd.self.root_hub);		/* empty the interrupt branches */	for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load [i] = 0;	for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0;		/* no EDs to remove */	ohci->ed_rm_list [0] = NULL;	ohci->ed_rm_list [1] = NULL;	/* empty control and bulk lists */	 	ohci->ed_isotail     = NULL;	ohci->ed_controltail = NULL;	ohci->ed_bulktail    = NULL;	if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {		err ("can't restart %s, %d", ohci->hcd.self.bus_name, temp);		return temp;	} else		dbg ("restart %s completed", ohci->hcd.self.bus_name);	return 0;}static int ohci_resume (struct usb_hcd *hcd){	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);	int			temp;	int			retval = 0;	unsigned long		flags;#ifdef CONFIG_PMAC_PBOOK	{		struct device_node *of_node;		/* Re-enable USB PAD & cell clock */		of_node = pci_device_to_OF_node (hcd->pdev);		if (of_node)			pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1);	}#endif	/* did we suspend, or were we powered off? */	ohci->hc_control = readl (&ohci->regs->control);	temp = ohci->hc_control & OHCI_CTRL_HCFS;#ifdef DEBUG	/* the registers may look crazy here */	ohci_dump_status (ohci);#endif	/* Re-enable bus mastering */	pci_set_master (ohci->hcd.pdev);		switch (temp) {	case OHCI_USB_RESET:	// lost power		info ("USB restart: %s", hcd->self.bus_name);		retval = hc_restart (ohci);		break;	case OHCI_USB_SUSPEND:	// host wakeup	case OHCI_USB_RESUME:	// remote wakeup		info ("USB continue: %s from %s wakeup", hcd->self.bus_name,			 (temp == OHCI_USB_SUSPEND)				? "host" : "remote");		ohci->hc_control = OHCI_USB_RESUME;		writel (ohci->hc_control, &ohci->regs->control);		(void) readl (&ohci->regs->control);		mdelay (20); /* no schedule here ! */		/* Some controllers (lucent) need a longer delay here */		mdelay (15);		temp = readl (&ohci->regs->control);		temp = ohci->hc_control & OHCI_CTRL_HCFS;		if (temp != OHCI_USB_RESUME) {			err ("controller %s won't resume", hcd->self.bus_name);			ohci->disabled = 1;			retval = -EIO;			break;		}		/* Some chips likes being resumed first */		writel (OHCI_USB_OPER, &ohci->regs->control);		(void) readl (&ohci->regs->control);		mdelay (3);		/* Then re-enable operations */		spin_lock_irqsave (&ohci->lock, flags);		ohci->disabled = 0;		ohci->sleeping = 0;		ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;		if (!ohci->ed_rm_list [0] && !ohci->ed_rm_list [1]) {			if (ohci->ed_controltail)				ohci->hc_control |= OHCI_CTRL_CLE;			if (ohci->ed_bulktail)				ohci->hc_control |= OHCI_CTRL_BLE;		}		hcd->state = USB_STATE_READY;		writel (ohci->hc_control, &ohci->regs->control);		/* trigger a start-frame interrupt (why?) */		writel (OHCI_INTR_SF, &ohci->regs->intrstatus);		writel (OHCI_INTR_SF, &ohci->regs->intrenable);		/* Check for a pending done list */		writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);			(void) readl (&ohci->regs->intrdisable);		spin_unlock_irqrestore (&ohci->lock, flags); #ifdef CONFIG_PMAC_PBOOK		if (_machine == _MACH_Pmac)			enable_irq (hcd->pdev->irq); #endif		if (ohci->hcca->done_head)			dl_done_list (ohci, dl_reverse_done_list (ohci));		writel (OHCI_INTR_WDH, &ohci->regs->intrenable); 		/* assume there are TDs on the bulk and control lists */		writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus);// ohci_dump_status (ohci);dbg ("sleeping = %d, disabled = %d", ohci->sleeping, ohci->disabled);		break;	default:		warn ("odd PCI resume for %s", hcd->self.bus_name);	}	return retval;}#endif	/* CONFIG_PM *//*-------------------------------------------------------------------------*/static const char	hcd_name [] = "ohci-hcd";static const struct hc_driver ohci_driver = {	description:		hcd_name,	/*	 * generic hardware linkage	 */	irq:			ohci_irq,	flags:			HCD_MEMORY | HCD_USB11,	/*	 * basic lifecycle operations	 */	start:			ohci_start,#ifdef	CONFIG_PM	suspend:		ohci_suspend,	resume:			ohci_resume,#endif	stop:			ohci_stop,	/*	 * memory lifecycle (except per-request)	 */	hcd_alloc:		ohci_hcd_alloc,	hcd_free:		ohci_hcd_free,	/*	 * managing i/o requests and associated device resources	 */	urb_enqueue:		ohci_urb_enqueue,	urb_dequeue:		ohci_urb_dequeue,	free_config:		ohci_free_config,	/*	 * scheduling support	 */	get_frame_number:	ohci_get_frame,	/*	 * root hub support	 */	hub_status_data:	ohci_hub_status_data,	hub_control:		ohci_hub_control,};#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESCEXPORT_NO_SYMBOLS;MODULE_AUTHOR (DRIVER_AUTHOR);MODULE_DESCRIPTION (DRIVER_INFO);MODULE_LICENSE ("GPL");/*-------------------------------------------------------------------------*/#ifdef CONFIG_PCI/* There do exist non-PCI implementations of OHCI ... * Examples include the SA-1111 (ARM) and some MIPS * and related hardware. */static const struct pci_device_id __devinitdata pci_ids [] = { {	/* handle any USB OHCI controller */	class:		(PCI_CLASS_SERIAL_USB << 8) | 0x10,	class_mask:	~0,	driver_data:	(unsigned long) &ohci_driver,	/* no matter who makes it */	vendor:		PCI_ANY_ID,	device:		PCI_ANY_ID,	subvendor:	PCI_ANY_ID,	subdevice:	PCI_ANY_ID,	}, { /* end: all zeroes */ }};MODULE_DEVICE_TABLE (pci, pci_ids);/* pci driver glue; this is a "new style" PCI driver module */static struct pci_driver ohci_pci_driver = {	name:		(char *) hcd_name,	id_table:	pci_ids,	probe:		usb_hcd_pci_probe,	remove:		usb_hcd_pci_remove,#ifdef	CONFIG_PM	suspend:	usb_hcd_pci_suspend,	resume:		usb_hcd_pci_resume,#endif}; static int __init ohci_hcd_init (void) {	dbg (DRIVER_INFO);	dbg ("block sizes: ed %d td %d",		sizeof (struct ed), sizeof (struct td));	return pci_module_init (&ohci_pci_driver);}module_init (ohci_hcd_init);/*-------------------------------------------------------------------------*/static void __exit ohci_hcd_cleanup (void) {		pci_unregister_driver (&ohci_pci_driver);}module_exit (ohci_hcd_cleanup);#endif /* CONFIG_PCI */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -