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

📄 usb_ctl.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (C) Compaq Computer Corporation, 1998, 1999 *  Copyright (C) Extenex Corporation, 2001 *  Copyright (C) Intrinsyc, Inc., 2002 * *  PXA USB controller core driver. * *  This file provides interrupt routing and overall coordination *  of the endpoints. * *  Please see: *    linux/Documentation/arm/SA1100/SA1100_USB  *  for more info. * *  02-May-2002 *   Frank Becker (Intrinsyc) - derived from sa1100 usb_ctl.c * */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/proc_fs.h>#include <linux/tqueue.h>#include <linux/delay.h>#include <linux/slab.h>#include <asm/io.h>#include <asm/dma.h>#include <asm/irq.h>#include <asm/mach-types.h>#include "pxa_usb.h"#include "usb_ctl.h"//#define DEBUG 1#if DEBUGstatic unsigned int usb_debug = DEBUG;#else#define usb_debug 0     /* gcc will remove all the debug code for us */#endif//////////////////////////////////////////////////////////////////////////////// Prototypes//////////////////////////////////////////////////////////////////////////////int usbctl_next_state_on_event( int event );static void udc_int_hndlr(int, void *, struct pt_regs *);static void initialize_descriptors( void );static void soft_connect_hook( int enable );static void udc_disable(void);static void udc_enable(void);#if CONFIG_PROC_FS#define PROC_NODE_NAME "driver/pxausb"static int usbctl_read_proc(char *page, char **start, off_t off,							int count, int *eof, void *data);#endif//////////////////////////////////////////////////////////////////////////////// Globals//////////////////////////////////////////////////////////////////////////////static const char pszMe[] = "usbctl: ";struct usb_info_t usbd_info;  /* global to ep0, usb_recv, usb_send *//* device descriptors */static desc_t desc;#define MAX_STRING_DESC 8static string_desc_t * string_desc_array[ MAX_STRING_DESC ];static string_desc_t sd_zero;  /* special sd_zero holds language codes */// called when configuredstatic usb_notify_t configured_callback = NULL;enum {    kStateZombie		= 0,    kStateZombieSuspend		= 1,    kStateDefault		= 2,    kStateDefaultSuspend	= 3,    kStateAddr			= 4,    kStateAddrSuspend		= 5,    kStateConfig		= 6,    kStateConfigSuspend		= 7};/* * FIXME: The PXA UDC handles several host device requests without user  * notification/intervention. The table could be collapsed quite a bit... */static int device_state_machine[8][6] = {//              suspend               reset          resume         adddr       config        deconfig/* zombie */  { kStateZombieSuspend , kStateDefault, kStateZombie , kError    , kError      , kError },/* zom sus */ { kStateZombieSuspend , kStateDefault, kStateZombie , kError    , kError      , kError },/* default */ { kStateDefaultSuspend, kStateDefault, kStateDefault, kStateAddr, kStateConfig, kError },/* def sus */ { kStateDefaultSuspend, kStateDefault, kStateDefault, kError    , kError      , kError },/* addr */    { kStateAddrSuspend   , kStateDefault, kStateAddr   , kError    , kStateConfig, kError },/* addr sus */{ kStateAddrSuspend   , kStateDefault, kStateAddr   , kError    , kError      , kError },/* config */  { kStateConfigSuspend , kStateDefault, kStateConfig , kError    , kError      , kStateDefault },/* cfg sus */ { kStateConfigSuspend , kStateDefault, kStateConfig , kError    , kError      , kError }};/* "device state" is the usb device framework state, as opposed to the   "state machine state" which is whatever the driver needs and is much   more fine grained*/static int sm_state_to_device_state[8] = { //  zombie            zom suspend       USB_STATE_POWERED, USB_STATE_SUSPENDED, //  default           default susUSB_STATE_DEFAULT, USB_STATE_SUSPENDED,//  addr              addr sus         USB_STATE_ADDRESS, USB_STATE_SUSPENDED, //  config            config susUSB_STATE_CONFIGURED, USB_STATE_SUSPENDED};static char * state_names[8] ={ "zombie", "zombie suspended",   "default", "default suspended",  "address", "address suspended",   "configured", "config suspended"};static char * event_names[6] ={ "suspend", "reset", "resume",  "address assigned", "configure", "de-configure"};static char * device_state_names[] ={ "not attached", "attached", "powered", "default",  "address", "configured", "suspended" };static int sm_state = kStateZombie;//////////////////////////////////////////////////////////////////////////////// Async///////////////////////////////////////////////////////////////////////////////* The UDCCR reg contains mask and interrupt status bits, * so using '|=' isn't safe as it may ack an interrupt. */void udc_set_mask_UDCCR( int mask ){	UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS);}void udc_clear_mask_UDCCR( int mask){	UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS);}void udc_ack_int_UDCCR( int mask){	/* udccr contains the bits we dont want to change */	__u32 udccr = UDCCR & UDCCR_MASK_BITS; 	UDCCR = udccr | (mask & ~UDCCR_MASK_BITS);}static voidudc_int_hndlr(int irq, void *dev_id, struct pt_regs *regs){  	__u32 status = UDCCR;  	__u32 ir0_status = USIR0;  	__u32 ir1_status = USIR1;  	__u32 uicr0 = UICR0;  	__u32 uicr1 = UICR1;	//mask ints	udc_set_mask_UDCCR( UDCCR_REM | UDCCR_SRM);	UICR0 = 0xff;	UICR1 = 0xff;	if( usb_debug > 2)	{		printk("%s--- udc_int_hndlr\n"		   "UDCCR=0x%08x UDCCS0=0x%08x UDCCS1=0x%08x UDCCS2=0x%08x\n"		   "USIR0=0x%08x USIR1=0x%08x UICR0=0x%08x UICR1=0x%08x\n", 		    pszMe, status, UDCCS0, UDCCS1, UDCCS2, ir0_status, ir1_status, uicr0, uicr1);	}	/* SUSpend Interrupt Request */	if ( status & UDCCR_SUSIR )	{		udc_ack_int_UDCCR( UDCCR_SUSIR);		if( usb_debug) printk("%sSuspend...\n", pszMe);		usbctl_next_state_on_event( kEvSuspend );	}	/* RESume Interrupt Request */	if ( status & UDCCR_RESIR )	{		udc_ack_int_UDCCR( UDCCR_RESIR);		if( usb_debug) printk("%sResume...\n", pszMe);		usbctl_next_state_on_event( kEvResume );	}	/* ReSeT Interrupt Request - UDC has been reset */	if ( status & UDCCR_RSTIR )	{		/* clear the reset interrupt */		udc_ack_int_UDCCR( UDCCR_RSTIR);		/* check type of reset */		if( (UDCCR & UDCCR_UDA) == 0)		{			/* reset assertion took place, nothing to do */			if( usb_debug) printk("%sReset assertion...\n", pszMe);		}		/* ok, it's a reset negation, go on with reset */		else if ( usbctl_next_state_on_event( kEvReset ) != kError )		{			/* starting reset sequence now... */			if( usb_debug) printk("%sResetting\n", pszMe);			ep0_reset();			ep_bulk_in1_reset();			ep_bulk_out1_reset();			usbctl_next_state_on_event( kEvConfig );		}		else		{			printk("%sUnexpected reset\n", pszMe);		}	}	else	{		/* ep0 int */		if (ir0_status & USIR0_IR0)			ep0_int_hndlr();		/* transmit bulk */		if (ir0_status & USIR0_IR1)			ep_bulk_in1_int_hndlr(ir0_status);		/* receive bulk */		if ( ir0_status & USIR0_IR2)			ep_bulk_out1_int_hndlr(ir0_status);		while (UDCCS2 & UDCCS_BO_RNE)		{			if( usb_debug) printk("More Bulk-out data...\n");			ep_bulk_out1_int_hndlr(ir0_status);		}	}	UICR0 = uicr0;	UICR1 = uicr1;	udc_clear_mask_UDCCR( UDCCR_SRM | UDCCR_REM); /* enable suspend/resume, reset */	/* clear all endpoint ints */	USIR0 |= 0xff;	USIR1 |= 0xff;	if( usb_debug > 2)	{		printk("%sudc_int_hndlr\n"		       "UDCCR=0x%08x UDCCS0=0x%08x UDCCS1=0x%08x UDCCS2=0x%08x\n"		       "USIR0=0x%08x USIR1=0x%08x UICR0=0x%08x UICR1=0x%08x\n", 			pszMe, UDCCR, UDCCS0, UDCCS1, UDCCS2, USIR0, USIR1, UICR0, UICR1);	}}//////////////////////////////////////////////////////////////////////////////// Public Interface///////////////////////////////////////////////////////////////////////////////* Open PXA usb core on behalf of a client, but don't start running */intpxa_usb_open( const char * client ){	if ( usbd_info.client_name != NULL )	{		printk( "%sUnable to register %s (%s already registered).\n", 			pszMe, client, usbd_info.client_name );		return -EBUSY;	}	usbd_info.client_name = (char*) client;	memset(&usbd_info.stats, 0, sizeof(struct usb_stats_t));	memset(string_desc_array, 0, sizeof(string_desc_array));	/* hack to start in zombie suspended state */	sm_state = kStateZombieSuspend;	usbd_info.state = USB_STATE_SUSPENDED;	/* create descriptors for enumeration */	initialize_descriptors();	printk( "%s%s registered.\n", pszMe, client );	return 0;}/* Start running. Must have called usb_open (above) first */intpxa_usb_start( void ){	if ( usbd_info.client_name == NULL ) {		printk( "%s%s - no client registered\n",				pszMe, __FUNCTION__ );		return -EPERM;	}	/* start UDC internal machinery running */	udc_enable();	udelay( 100 );	/* flush DMA and fire through some -EAGAINs */	ep_bulk_out1_init( usbd_info.dmach_rx );	ep_bulk_in1_init( usbd_info.dmach_tx );	/* give endpoint notification we are starting */	ep_bulk_out1_state_change_notify( USB_STATE_SUSPENDED );	ep_bulk_in1_state_change_notify( USB_STATE_SUSPENDED );	/* enable any platform specific hardware */	soft_connect_hook( 1 );	/* enable suspend/resume, reset */	udc_clear_mask_UDCCR( UDCCR_SRM | UDCCR_REM); 	/* enable ep0, ep1, ep2 */	UICR0 &= ~(UICR0_IM0 | UICR0_IM1 | UICR0_IM2); 	if( usb_debug) printk( "%sStarted %s\n", pszMe, usbd_info.client_name );	return 0;}/* Stop USB core from running */intpxa_usb_stop( void ){	if ( usbd_info.client_name == NULL ) {		printk( "%s%s - no client registered\n",				pszMe, __FUNCTION__ );		return -EPERM;	}	/* mask everything */	/* disable suspend/resume, reset */	udc_set_mask_UDCCR( UDCCR_SRM | UDCCR_REM); 	/* disable ep0, ep1, ep2 */	UICR0 |= (UICR0_IM0 | UICR0_IM1 | UICR0_IM2); 	ep_bulk_out1_reset();	ep_bulk_in1_reset();	udc_disable();	if( usb_debug) printk( "%sStopped %s\n", pszMe, usbd_info.client_name );	return 0;}/* Tell PXA core client is through using it */intpxa_usb_close( void ){	 if ( usbd_info.client_name == NULL ) {		  printk( "%s%s - no client registered\n",				  pszMe, __FUNCTION__ );		  return -EPERM;	 }	 printk( "%s%s closed.\n", pszMe, (char*)usbd_info.client_name );	 usbd_info.client_name = NULL;	 return 0;}/* set a proc to be called when device is configured */usb_notify_t pxa_set_configured_callback( usb_notify_t func ){	 usb_notify_t retval = configured_callback;	 configured_callback = func;	 return retval;}/*==================================================== * Descriptor Manipulation. * Use these between open() and start() above to setup * the descriptors for your device. * */

⌨️ 快捷键说明

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