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

📄 usb-ohci-pci.c

📁 S3C2440ARM9开发板的USB驱动程序
💻 C
字号:
#include <linux/module.h>#include <linux/pci.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/interrupt.h>  /* for in_interrupt() */#undef DEBUG#include <linux/usb.h>#include "usb-ohci.h"#ifdef CONFIG_PMAC_PBOOK#include <asm/machdep.h>#include <asm/pmac_feature.h>#include <asm/pci-bridge.h>#ifndef CONFIG_PM#define CONFIG_PM#endif#endif/*-------------------------------------------------------------------------*//* Increment the module usage count, start the control thread and * return success. */static struct pci_driver ohci_pci_driver;static int __devinithc_found_ohci (struct pci_dev *dev, int irq,	void *mem_base, const struct pci_device_id *id){	ohci_t * ohci;	char buf[8], *bufp = buf;	int ret;#ifndef __sparc__	sprintf(buf, "%d", irq);#else	bufp = __irq_itoa(irq);#endif	printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n",		(unsigned long)	mem_base, bufp);	printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);    	ohci = hc_alloc_ohci (dev, mem_base);	if (!ohci) {		return -ENOMEM;	}	if ((ret = ohci_mem_init (ohci)) < 0) {		hc_release_ohci (ohci);		return ret;	}	ohci->flags = id->driver_data;	/* Check for NSC87560. We have to look at the bridge (fn1) to identify	   the USB (fn2). This quirk might apply to more or even all NSC stuff	   I don't know.. */	   	if(dev->vendor == PCI_VENDOR_ID_NS)	{		struct pci_dev *fn1  = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1));		if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO)			ohci->flags |= OHCI_QUIRK_SUCKYIO;			}		if (ohci->flags & OHCI_QUIRK_SUCKYIO)		printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n");	if (ohci->flags & OHCI_QUIRK_AMD756)		printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n");	if (hc_reset (ohci) < 0) {		hc_release_ohci (ohci);		return -ENODEV;	}	/* FIXME this is a second HC reset; why?? */	writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control);	wait_ms (10);	usb_register_bus (ohci->bus);		if (request_irq (irq, hc_interrupt, SA_SHIRQ,			ohci_pci_driver.name, ohci) != 0) {		err ("request interrupt %s failed", bufp);		hc_release_ohci (ohci);		return -EBUSY;	}	ohci->irq = irq;     	if (hc_start (ohci) < 0) {		err ("can't start usb-%s", dev->slot_name);		hc_release_ohci (ohci);		return -EBUSY;	}#ifdef	DEBUG	ohci_dump (ohci, 1);#endif	return 0;}/*-------------------------------------------------------------------------*//* configured so that an OHCI device is always provided *//* always called with process context; sleeping is OK */static int __devinitohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id){	unsigned long mem_resource, mem_len;	void *mem_base;	int status;	if (pci_enable_device(dev) < 0)		return -ENODEV;        if (!dev->irq) {        	err("found OHCI device with no IRQ assigned. check BIOS settings!");		pci_disable_device (dev);   	        return -ENODEV;        }		/* we read its hardware registers as memory */	mem_resource = pci_resource_start(dev, 0);	mem_len = pci_resource_len(dev, 0);	if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {		dbg ("controller already in use");		pci_disable_device (dev);		return -EBUSY;	}	mem_base = ioremap_nocache (mem_resource, mem_len);	if (!mem_base) {		err("Error mapping OHCI memory");		release_mem_region (mem_resource, mem_len);		pci_disable_device (dev);		return -EFAULT;	}	/* controller writes into our memory */	pci_set_master (dev);		status = hc_found_ohci (dev, dev->irq, mem_base, id);	if (status < 0) {		iounmap (mem_base);		release_mem_region (mem_resource, mem_len);		pci_disable_device (dev);	}	return status;} /*-------------------------------------------------------------------------*//* may be called from interrupt context [interface spec] *//* may be called without controller present *//* may be called with controller, bus, and devices active */static void __devexitohci_pci_remove (struct pci_dev *dev){	ohci_t		*ohci = (ohci_t *) pci_get_drvdata(dev);	dbg ("remove %s controller usb-%s%s%s",		hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),		dev->slot_name,		ohci->disabled ? " (disabled)" : "",		in_interrupt () ? " in interrupt" : ""		);	hc_remove_ohci(ohci);	release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));	pci_disable_device (dev);}#ifdef	CONFIG_PM/*-------------------------------------------------------------------------*/static intohci_pci_suspend (struct pci_dev *dev, u32 state){	ohci_t			*ohci = (ohci_t *) pci_get_drvdata(dev);	extern int ohci_suspend(ohci_t *, u32);	return ohci_suspend(ohci, state);}/*-------------------------------------------------------------------------*/static intohci_pci_resume (struct pci_dev *dev){	ohci_t		*ohci = (ohci_t *) pci_get_drvdata(dev);	extern int ohci_resume(ohci_t *);	return ohci_resume(ohci);}#endif	/* CONFIG_PM *//*-------------------------------------------------------------------------*/static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {	/*	 * AMD-756 [Viper] USB has a serious erratum when used with	 * lowspeed devices like mice.	 */	vendor:		0x1022,	device:		0x740c,	subvendor:	PCI_ANY_ID,	subdevice:	PCI_ANY_ID,	driver_data:	OHCI_QUIRK_AMD756,} , {	/* handle any USB OHCI controller */	class: 		((PCI_CLASS_SERIAL_USB << 8) | 0x10),	class_mask: 	~0,	/* 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, ohci_pci_ids);static struct pci_driver ohci_pci_driver = {	name:		"usb-ohci",	id_table:	&ohci_pci_ids [0],	probe:		ohci_pci_probe,	remove:		__devexit_p(ohci_pci_remove),#ifdef	CONFIG_PM	suspend:	ohci_pci_suspend,	resume:		ohci_pci_resume,#endif	/* PM */}; /*-------------------------------------------------------------------------*/static int __init ohci_hcd_init (void) {	return pci_module_init (&ohci_pci_driver);}/*-------------------------------------------------------------------------*/static void __exit ohci_hcd_cleanup (void) {		pci_unregister_driver (&ohci_pci_driver);}module_init (ohci_hcd_init);module_exit (ohci_hcd_cleanup);

⌨️ 快捷键说明

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