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

📄 wmmx.c

📁 S3C2440ARM9开发板的USB驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	udcisr0 = UDCISR0;	udcisr1 = UDCISR1 & 0xffff;	while (udcisr0 || udcisr1) {		u32 udccsr0 = UDCCSR0;		WMMX_IRO(udcisr0, "------------------------> Interrupt");		/* For Endpoint0, Endpoint A-P */		for (ep = 0; udcisr0 != 0 && ep < 16 ; udcisr0 >>= 2, ep++) {			if (udcisr0 & UDC_INT_PACKETCMP) {				switch (ep_maps[ep].eptype) {				case ep_control:					wmmx_ep0(phys_ep_to_endpoints[0], 						 udccsr0);					break;				case ep_bulk_in:				case ep_interrupt:					if (wmmx_usb_dma_configs[ep].dma_enabled)					{						wmmx_ep_reset_interrupt_status(ep);						break;					}					wmmx_in_n(ep, phys_ep_to_endpoints[ep]);					break;				case ep_bulk_out:					if (wmmx_usb_dma_configs[ep].dma_enabled)					{						wmmx_ep_reset_interrupt_status(ep);						break;					}										while (UDCCSN(ep) & UDCCSR_PC) {						wmmx_out_n(ep, 							phys_ep_to_endpoints[ep]);					}					break;				case ep_iso_in:				case ep_iso_out:					wmmx_ep_reset_interrupt_status(ep);					break;				}			}			if (udcisr0 & UDC_INT_FIFOERROR) {				printk("FIFO error on %d endpoint\n", ep);			}		}		/* For Endpoint Q-X */		for ( ; udcisr1 != 0 && ep < 24; udcisr1 >>= 2, ep++) {			/* I will rebuild ep_maps array */			if (udcisr1 & UDC_INT_PACKETCMP) {				switch (ep_maps[ep].eptype) {				case ep_bulk_in:				case ep_interrupt:					wmmx_in_n(ep, phys_ep_to_endpoints[ep]);					break;				case ep_bulk_out:					while (UDCCSN(ep) & UDCCSR_PC) {						wmmx_out_n(ep, 							phys_ep_to_endpoints[ep]);					}					break;				case ep_iso_in:				case ep_iso_out:					wmmx_ep_reset_interrupt_status(ep);					break;				default:					break;				}			}		}		udcisr0 = UDCISR0;		udcisr1 = UDCISR1 & 0xffff;	}	/* Reset, Suspend, Resume interrupts */	udcisr1 = UDCISR1;	/* UDC Reset */	if (udcisr1 & UDCISR1_IERS) {		WMMX_CCR(udccr, "------------------------> Reset");		udc_suspended = 0;		usbd_device_event (udc_device, DEVICE_RESET, 0);		usbd_device_event (udc_device, DEVICE_ADDRESS_ASSIGNED, 0);			UDCISR1 = UDCISR1_IERS;	}	/* UDC Resume */	if (udcisr1 & UDCISR1_IERU) {		WMMX_CCR(udccr, "------------------------> Resume");		if (udc_suspended) {			udc_suspended = 0;			usbd_device_event (udc_device, DEVICE_BUS_ACTIVITY, 0);		}		UDCISR1 = UDCISR1_IERU;	}	/* UDC Suspend */	if (udcisr1 & UDCISR1_IESU) {		WMMX_CCR(udccr, "------------------------> Suspend");		if (!udc_suspended) {			udc_suspended = 1;			usbd_device_event (udc_device, DEVICE_BUS_INACTIVE, 0);		}		UDCISR1 = UDCISR1_IESU;	}			/* Configuration Change Interrupt */	if (udcisr1 & UDCISR1_IECC) {		WMMX_CCR(udccr, "------------------------> Configuration "				"Changed");		UDCCR |= UDCCR_SMAC;					udc_device->configuration = (UDCCR & UDCCR_ACN) >> UDCCR_ACN_S;		udc_device->interface = (UDCCR & UDCCR_AIN) >> UDCCR_AIN_S;		udc_device->alternate = (UDCCR & UDCCR_AAISN) >> UDCCR_AAISN_S;		usbd_device_event(udc_device, DEVICE_CONFIGURED, 0); 		UDCISR1 = UDCISR1_IECC;	}	WMMX_CCR(UDCCR, "<-- Interrupt");}/* * Setting the endpoint configuration register */static int udc_set_endpoint(struct usb_endpoint_description* endpoint,			    int configuration, int interface,			    int alternate, int eps, int accum_size){	u32 config_reg;	static int phys_endpoints = 0;		phys_endpoints ++;	config_reg = ((configuration << UDCCONR_CN_S) & UDCCONR_CN) |		     ((interface << UDCCONR_IN_S) & UDCCONR_IN) |		     ((alternate << UDCCONR_AISN_S) & UDCCONR_AISN) |		     ((eps << UDCCONR_EN_S) & UDCCONR_EN);		logic_to_phys_eps[configuration][endpoint->bEndpointAddress & 0xf] = 		phys_endpoints;	/* Double Buffering Enabled and Enable the EP */	config_reg |= UDCCONR_EE | UDCCONR_DE;		if (endpoint->direction == IN) {		config_reg |= UDCCONR_ED;	/* Direction: IN */	} else {		config_reg &= ~UDCCONR_ED;	/* Direction: OUT*/	}	config_reg |= ((endpoint->bmAttributes << UDCCONR_ET_S) & UDCCONR_ET) |		      ((endpoint->wMaxPacketSize << UDCCONR_MPS_S) &		       UDCCONR_MPS);	UDCCN(phys_endpoints) = config_reg;	ep_maps[phys_endpoints].logical = endpoint->bEndpointAddress;	ep_maps[phys_endpoints].eptype = 		(((config_reg & UDCCONR_ET) >> UDCCONR_ET_S) << 1) |		 !!(config_reg & UDCCONR_ED);	ep_maps[phys_endpoints].size = endpoint->wMaxPacketSize;	ep_maps[phys_endpoints].accum_size = accum_size;	return 0;}/* * Check the function driver and set UDC Endpoint A-X Configuration Registers */static int udc_check_function(struct usb_function_instance* function){	int total = 1;	int i,j,k,m;	struct usb_configuration_description* configuration;	struct usb_interface_description* interface;	struct usb_alternate_description* alternate;	struct usb_endpoint_description* endpoint;	if (function->function_driver->configurations > 	    MAX_LOGICAL_CONFIGURATIONS) {		printk(KERN_ERR"Too many configurations.\n");		return -1;	}	for (i = 0; i < function->function_driver->configurations; i++) {		configuration = function->function_driver->configuration_description + i;		for (j = 0; j < configuration->interfaces; j++) {			int logical_endpoints = 1;			interface = configuration->interface_list + j;			for (k = 0; k < interface->alternates; k++) {				alternate = interface->alternate_list + k;				for (m = 0; m < alternate->endpoints; m++) {					if (alternate->endpoints > 					    MAX_LOGICAL_ENDPOINTS) {						printk(KERN_ERR "Too many logical endpoints.\n");						return -1;					}					endpoint = alternate->endpoint_list + m;					if (udc_set_endpoint(endpoint, i+1, 							     j, k, 							     logical_endpoints++,							     (interface->bInterfaceClass ==							      USB_CLASS_MASS_STORAGE) ?							      WMMX_STORAGE_ACCUM_SIZE : 0) < 0)					{						printk(KERN_ERR "udc_set_endpoint() error.\n");						return -1;					}					total++;				}			}		}	}	return total;}/* * Enable UDC configuration setting */static int udc_configuration_enable(struct usb_device_instance* device){	struct usb_function_instance* function;	int count, i;		count = i = 0;	function = device->function_instance_array + i;	if (!function) {		printk(KERN_ERR"No valid function driver!\n");		return -1;	}	count = udc_check_function(function);	if (count < 0) {		printk(KERN_ERR"udc_check_function(...) failed.\n");		return -1;	}	return 0;}/* * Public Functions. *//* * udc_start_in_irq - start transmit * @eendpoint: endpoint instance * * Called by bus interface driver to see if we need to  * start a data transmission. */void udc_start_in_irq (struct usb_endpoint_instance *endpoint){	int phys_ep = wmmx_logic_to_phys_ep(endpoint->endpoint_address & 0xf);	if (endpoint->endpoint_address == 0) {		struct urb* urb = endpoint->tx_urb;		if (!urb) {			printk(KERN_INFO "udc_start_in_irq() urb is NULL\n");			return;		}		wmmx_ep0xmit(endpoint, UDCCSR0);	} else if (UDCCSN(phys_ep) & UDCCSR_FS) {		if (wmmx_usb_dma_configs[phys_ep].dma_enabled)			wmmx_start_n_dma(phys_ep, endpoint);		else			wmmx_start_n(phys_ep, endpoint);	}}/* * udc_init - initialize * * Return non-zero if we cannot see device. */int udc_init (void){	int i;	dbg_tx(6, "udc_init:\n");	udc_disable_interrupts (NULL);	for (i = 0; i < UDC_MAX_ENDPOINTS; i++) {		memset(&wmmx_usb_dma_configs[i], 0, 		       sizeof(struct wmmx_usb_dma_config));	}	for (i = 0; i < 16; i++) {		wmmx_dmach_to_configs[i] = NULL;	}	wmmx_usb_dma_next = wmmx_usb_dma_buffer = 		consistent_alloc(GFP_KERNEL, DMA_BUFFER_SIZE, 				 &wmmx_usb_dma_phys_buffer);	if (!wmmx_usb_dma_buffer) {		printk(KERN_ERR"udc_init: consistent_alloc() failed\n");		return 1;	}	return 0;}/* * udc_start_in - start transmit * @eendpoint: endpoint instance * * Called by bus interface driver to see if we need to start  * a data transmission. */void udc_start_in (struct usb_endpoint_instance *endpoint){	if (endpoint) {		unsigned long flags;		local_irq_save (flags);		udc_start_in_irq(endpoint);		local_irq_restore (flags);	}}/* * udc_stall_ep - stall endpoint * @ep: physical endpoint * * Stall the endpoint. */void udc_stall_ep (unsigned int phys_ep){	dbg_usbe(5, "usc_stall_ep ep=%d\n", phys_ep);	if (phys_ep < UDC_MAX_ENDPOINTS) {		UDCCSN(phys_ep) |= UDCCSR_FST;	}}/* * udc_reset_ep - reset endpoint * @ep: physical endpoint * reset the endpoint. * * returns : 0 if ok, -1 otherwise */void udc_reset_ep (unsigned int phys_ep){	if (phys_ep == 0) {		UDCCSN(phys_ep) |= ((UDCCSN(phys_ep) & UDCCSR_DME) | 				    UDCCSR_FEF);	}}/* * udc_endpoint_halted - is endpoint halted * @ep: * * Return non-zero if endpoint is halted */int udc_endpoint_halted (unsigned int phys_ep){	return 0;}/* * udc_set_address - set the USB address for this device * @address: * * Called from control endpoint function after it decodes  * a set address setup packet. */void udc_set_address (unsigned char address){}/* * udc_serial_init - set a serial number if available */int __init udc_serial_init (struct usb_bus_instance *bus){	return -EINVAL;}/* * udc_max_endpoints - max physical endpoints  * * Return number of physical endpoints. */int udc_max_endpoints (void){	return UDC_MAX_ENDPOINTS;}/* * udc_check_ep - check logical endpoint  * @lep: * * Return physical endpoint number to use for this logical  * endpoint or zero if not valid. */int udc_check_ep(int logic_ep, int packetsize){	if (packetsize > 64)		return 0;	return wmmx_logic_to_phys_ep(logic_ep & 0x0f);}static int wmmx_usb_dma_init(unsigned int phys_ep, struct usb_endpoint_instance* endpoint){	wmmx_usb_dma_configs[phys_ep].ep = phys_ep;	wmmx_usb_dma_configs[phys_ep].endpoint = endpoint;	if (ep_maps[phys_ep].eptype == ep_bulk_in) {		wmmx_usb_dma_configs[phys_ep].dma_channel = 			pxa_request_dma("WMMX DMA IN", 0, 					wmmx_usb_dma_tx_irq, 					&wmmx_usb_dma_configs[phys_ep]);		if (wmmx_usb_dma_configs[phys_ep].dma_channel < 0) {			printk(KERN_ERR "pxa_request_dma(WMMX DMA IN) "					"failed %d\n",			       wmmx_usb_dma_configs[phys_ep].dma_channel);			return 1;		}		if ((wmmx_usb_dma_next - wmmx_usb_dma_buffer) > 		    DMA_BUFFER_SIZE) {			printk(KERN_ERR"Out of memory\n");			return 1;		}				wmmx_usb_dma_configs[phys_ep].dma_buffer = wmmx_usb_dma_next;		wmmx_usb_dma_configs[phys_ep].dma_phys_buffer = 			wmmx_usb_dma_phys_buffer + 			(wmmx_usb_dma_next - wmmx_usb_dma_buffer);		wmmx_usb_dma_next = 			(void *)(((u32)wmmx_usb_dma_next + 				  endpoint->tx_packetSize + 3) & ~3);		wmmx_dmach_to_configs[wmmx_usb_dma_configs[phys_ep].dma_channel] = 			&wmmx_usb_dma_configs[phys_ep];		wmmx_usb_dma_configs[phys_ep].dma_enabled = 1;	} else if (ep_maps[phys_ep].eptype == ep_bulk_out) {		wmmx_usb_dma_configs[phys_ep].dma_channel = 			pxa_request_dma("WMMX DMA OUT", 0,					wmmx_usb_dma_rx_irq,					&wmmx_usb_dma_configs[phys_ep]);		if (wmmx_usb_dma_configs[phys_ep].dma_channel < 0) {			printk(KERN_ERR"pxa_request_dma(WMMX_DMA_OUT) failed %d\n",			       wmmx_usb_dma_configs[phys_ep].dma_channel);			return 1;		}		wmmx_usb_dma_configs[phys_ep].dma_buffer = wmmx_usb_dma_next;		wmmx_usb_dma_configs[phys_ep].dma_phys_buffer = 			wmmx_usb_dma_phys_buffer + 			(wmmx_usb_dma_next - wmmx_usb_dma_buffer);		wmmx_usb_dma_next = 			(void *)(((u32)wmmx_usb_dma_next + 				  endpoint->tx_packetSize + 3) & ~3);		wmmx_dmach_to_configs[wmmx_usb_dma_configs[phys_ep].dma_channel] = 			&wmmx_usb_dma_configs[phys_ep];		wmmx_usb_dma_configs[phys_ep].dma_enabled = 1;	} else {		printk(KERN_ERR"wmmx_usb_dma_init(): invalid endpoint type.\n");		wmmx_usb_dma_configs[phys_ep].dma_enabled = 0;		return 1;	}	return 0;}/* * udc_set_ep - setup endpoint  * @ep: * @endpoint: * * Associate a physical endpoint with endpoint_instance */void udc_setup_ep (struct usb_device_instance *device, 		   unsigned int phys_ep,		   struct usb_endpoint_instance *endpoint){	if (phys_ep < UDC_MAX_ENDPOINTS) {		phys_ep_to_endpoints[phys_ep] = endpoint;		if (phys_ep == 0) {			printk(KERN_DEBUG "udc_setup_ep: 0 do nothing\n");			wmmx_enable_ep_interrupt(0, (UDC_INT_FIFOERROR | 						     UDC_INT_PACKETCMP)); 		} else if (endpoint->endpoint_address & 0x80) { /* IN */			/* only support bulk in DMA mode now */			/* When you implement your function driver, you should 			   decide whether the endpoint will use DMA mode or 			   not */#ifdef CONFIG_USBD_WMMX_DMA_IN			if ((ep_maps[phys_ep].eptype == ep_bulk_in) &&			    (!wmmx_usb_dma_configs[phys_ep].dma_enabled)) {				if (!wmmx_usb_dma_init(phys_ep, endpoint)) {					UDCCSN(phys_ep) |= UDCCSR_DME;				}			}#endif			/* if dma can't be initialized successfully, we 			   enable the interrupt. */			if (!wmmx_usb_dma_configs[phys_ep].dma_enabled) {				wmmx_enable_ep_interrupt(phys_ep, 							 (UDC_INT_FIFOERROR |							  UDC_INT_PACKETCMP));			}		} else if (endpoint->endpoint_address) { /* OUT */			usbd_fill_rcv (device, endpoint, 5);			endpoint->rcv_urb = first_urb_detached(&endpoint->rdy);			/* When you implement your function driver, you should 			   decide whether the endpoint will use DMA mode or 			   not */#ifdef CONFIG_USBD_WMMX_DMA_OUT			if ((ep_maps[phys_ep].eptype == ep_bulk_out) &&			    (!wmmx_usb_dma_configs[phys_ep].dma_enabled)) {				if (!wmmx_usb_dma_init(phys_ep, endpoint)) {					int channel;

⌨️ 快捷键说明

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