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

📄 wmmx.c

📁 S3C2440ARM9开发板的USB驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	usbd_tx_complete_irq(endpoint, 0);	if (config->size < endpoint->tx_packetSize)		return;	else	{		wmmx_start_n_dma(config->ep, endpoint);	}}static void wmmx_start_n(unsigned int phys_ep, 			 struct usb_endpoint_instance *endpoint){	if (endpoint->tx_urb) {		int last;		struct urb *urb = endpoint->tx_urb;		if ((last = MIN(urb->actual_length - 				(endpoint->sent + endpoint->last), 				endpoint->tx_packetSize))) {			int size = last;			u32 *data = (u32*)(urb->buffer + endpoint->sent + 					   endpoint->last);			u32 *cp;			int remain = 0;			u8 *rd;			WMMX_XFER(WMMX_XFER_DIR_IN, last, (char *)data);			cp = data;			remain = size & 0x03;			size &= ~0x03;			while (size > 0) {				UDCDN(phys_ep) = *cp++;				size -= 4;			}						if (remain) {				volatile u8 *reg = 					(volatile u8 *)PUDCDN(phys_ep);				rd = (u8 *)cp;				while (remain--) {					*reg = *rd++;				}			}			if ((last < endpoint->tx_packetSize) ||			    ((endpoint->tx_urb->actual_length - 			      endpoint->sent) == last)) {				if (last != endpoint->tx_packetSize)				{				UDCCSN(phys_ep) = (UDCCSN(phys_ep) & 						   UDCCSR_WR_MASK) |						  UDCCSR_SP;			}			}			endpoint->last += last;		} else {			usbd_tx_complete_irq (endpoint, 0);		}	}}static void wmmx_in_n(unsigned int phys_ep, 		      struct usb_endpoint_instance *endpoint){	int udccsn;	wmmx_ep_reset_interrupt_status(phys_ep);	/* if TPC update tx urb and clear TPC */	if ((udccsn = UDCCSN(phys_ep)) & UDCCSR_PC) {                UDCCSN(phys_ep) = (UDCCSN(phys_ep) & UDCCSR_WR_MASK) |				  UDCCSR_PC;		usbd_tx_complete_irq(endpoint, 0);	}	if (udccsn & UDCCSR_FS) {		wmmx_start_n(phys_ep, endpoint);	}	/* clear underrun, not much we can do about it */	if (udccsn & UDCCSR_TRN) {		UDCCSN(phys_ep) = (UDCCSN(phys_ep) & UDCCSR_WR_MASK) |				  UDCCSR_TRN;	}}static void wmmx_usb_dma_rx_irq(int dmach, void* dev_id, struct pt_regs *regs){	unsigned int dcsr = DCSR(dmach);	struct wmmx_usb_dma_config *config = wmmx_dmach_to_configs[dmach];	struct usb_endpoint_instance *endpoint = config->endpoint;	unsigned int phys_ep = config->ep;	DCSR(dmach) &= ~DCSR_RUN;		if (dcsr & DCSR_BUSERR) {		DCSR(dmach) |= DCSR_BUSERR;		printk(KERN_ERR"DMA bus error\n");	} else if (dcsr & DCSR_ENRINTR) {		DCSR(dmach) |= DCSR_ENDINTR;			if (!endpoint->rcv_urb) {			endpoint->rcv_urb = first_urb_detached(&endpoint->rdy);		}		if (endpoint->rcv_urb) {			int len;			int stop_accumulation;			unsigned char* cp = endpoint->rcv_urb->buffer + 					    endpoint->rcv_urb->actual_length;			if (UDCCSN(config->ep) & UDCCSR_SP) {				len = endpoint->rcv_packetSize - 				     (DCMD(dmach) & DCMD_LENGTH);			} else {				len = endpoint->rcv_packetSize;			}						memcpy(cp, config->dma_buffer, len);			stop_accumulation = ((ep_maps[phys_ep].accum_size > 0) &&					     (endpoint->rcv_urb->actual_length + len ==					      ep_maps[phys_ep].accum_size));							WMMX_XFER(WMMX_XFER_DIR_OUT, len, endpoint->rcv_urb->buffer +				  endpoint->rcv_urb->actual_length);			usbd_rcv_complete_irq (endpoint, len, 0);			/* simulate ZLP to stop accumulating the data */			if (stop_accumulation)			{				usbd_rcv_complete_irq (endpoint, 0, 0);			}			if (len == 0) {				UDCCSN(config->ep) = UDCCSR_SP | 						     UDCCSR_PC | 						     ((UDCCSN(config->ep) & 						       UDCCSR_WR_MASK));			} else if (len < endpoint->rcv_packetSize) {				UDCCSN(config->ep) = UDCCSR_PC | 						     ((UDCCSN(config->ep) & 						       UDCCSR_WR_MASK));			}		}	} else		printk(KERN_ERR"DCSR(%d) = 0x%08x\n", dmach, DCSR(dmach));	/* Listen to the request */	DCSR(dmach) = DCSR_NODESC | DCSR_EORIRQEN;	DTADR(dmach) = wmmx_usb_dma_configs[config->ep].dma_phys_buffer;	DSADR(dmach) = PHYS_UDCDN(config->ep);	DCMD(dmach) = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_ENDIRQEN | 		      DCMD_BURST32 | DCMD_WIDTH4 | 		      (endpoint->rcv_packetSize & DCMD_LENGTH);		DRCMRUDC(config->ep) = dmach | DRCMR_MAPVLD;	DCSR(dmach) |= DCSR_RUN;}void wmmx_ep0recv(struct usb_endpoint_instance *endpoint, volatile u32 udccsr0){	struct urb *urb = endpoint->rcv_urb;	int retval;	WMMX_REGS(udccsr0, "         <-- setup data recv");	/* check for premature status stage */	if (!(udccsr0 & UDCCSR0_OPC) && !(udccsr0 & UDCCSR0_IPR)) {		if (urb->device_request.wLength == urb->actual_length) {			retval = usbd_recv_setup(ep0_urb);			if (retval != 0) {				UDCCSR0 = UDCCSR0_FST;				endpoint->state = WAIT_FOR_SETUP;				WMMX_REGS(udccsr0, "       --> bad setup FST");			}		} else {			urb->actual_length = 0;		}		endpoint->state = WAIT_FOR_SETUP; 	}	/* receive more data */	if ((udccsr0 & UDCCSR0_OPC) && !(udccsr0 & UDCCSR0_SA)) {		int size = urb->device_request.wLength;		u32* cp = (u32*) (urb->buffer + urb->actual_length);		while (size > 0) {			*cp++ = UDCDN(0);			size -= 4;		}		/* resize the actual length of URB structure. */		urb->actual_length += urb->device_request.wLength;		UDCCSR0 |= UDCCSR0_OPC;		/* to allow to enter a premature STATUS IN stage */		UDCCSR0 |= UDCCSR0_IPR;	}	return;}void wmmx_ep0xmit(struct usb_endpoint_instance *endpoint, volatile u32 udccsr0){	int short_packet;	int size;	struct urb *urb = endpoint->tx_urb;	WMMX_REGS(udccsr0, "          --> xmit");	/* check for premature status stage - host abandoned previous IN */	if ((udccsr0 & UDCCSR0_OPC) && !(udccsr0 & UDCCSR0_SA)) {		/* clear tx fifo and opr */		UDCCSR0 |= UDCCSR0_FTF | UDCCSR0_OPC;		endpoint->state = WAIT_FOR_SETUP;		endpoint->tx_urb = NULL;		endpoint->rcv_urb = NULL;		WMMX_REGS(UDCCSR0, "          <-- xmit premature status");		return;	}        /* check for stall */	if (udccsr0 & UDCCSR0_SST) {		/* clear stall and tx fifo */		UDCCSR0 |= UDCCSR0_SST | UDCCSR0_FTF;		endpoint->state = WAIT_FOR_SETUP;		endpoint->tx_urb = NULL;		endpoint->rcv_urb = NULL;		WMMX_REGS(UDCCSR0, "          <-- xmit stall");		return;	}	if (NULL == urb) {		size = 0;	} else {		endpoint->last = 		size = MIN(urb->actual_length - endpoint->sent, 			   endpoint->tx_packetSize);	}	short_packet = (size < endpoint->tx_packetSize);	WMMX_XMIT(size);	if (size > 0 && urb->buffer) {		u32* cp = (u32*)(urb->buffer + endpoint->sent);		int remain = 0;		u8 *rd;		remain = size & 0x03;		size &= ~0x3;		while (size) {			UDCDN(0) = *cp++;			size -= 4;		}				if (remain) {			volatile u8 *reg = (volatile u8 *)PUDCDN(0);			rd = (u8 *)cp;			while (remain--) {				*reg = *rd++;			}		}        }        if (!endpoint->tx_urb || (endpoint->last < endpoint->tx_packetSize)) {		/* Tell the UDC we are at the end of the packet. */		UDCCSR0 |= UDCCSR0_IPR;                endpoint->state = WAIT_FOR_OUT_STATUS;                WMMX_REGS(UDCCSR0, "          <-- xmit wait for status");	} else if ((endpoint->last == endpoint->tx_packetSize) && 		   ((endpoint->last + endpoint->sent) == 		    endpoint->tx_urb->actual_length)  &&                   ((endpoint->tx_urb->actual_length) <                     le16_to_cpu(endpoint->tx_urb->device_request.wLength))) {                endpoint->state = DATA_STATE_NEED_ZLP;                WMMX_REGS(UDCCSR0, "          <-- xmit need zlp");	} else {                WMMX_REGS(UDCCSR0, "          <-- xmit not finished");	}}void wmmx_ep0setup(struct usb_endpoint_instance *endpoint, u32 udccsr0){	if ((udccsr0 & (UDCCSR0_SA | UDCCSR0_OPC | UDCCSR0_RNE))	         == (UDCCSR0_SA | UDCCSR0_OPC | UDCCSR0_RNE)) {		u32 dummy;		int count;		int len;		int retval;                u32 *cp = (u32 *)&ep0_urb->device_request;                WMMX_REGS(udccsr0, "      --> setup");		count = len = UDCBCN(0);		if (count > 8) {			dbg_rx(6, "Received a setup packet(len(%d)>8\n", len);			if (!(winhost_flag || udcbegin_flag)) {			printk(KERN_INFO "Received a setup packet(len(%d)>8)\n",			       len);		}			count = 8;		}		while (count > 0) {                        *cp++ = UDCDN(0);			count -= 4;			len -= 4;		}		while (len > 0) {			dummy = UDCDN(0);			len -= 4;                }                WMMX_SETUP(&ep0_urb->device_request);		if (((ep0_urb->device_request.bmRequestType & 		      USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) && 	            le16_to_cpu(ep0_urb->device_request.wLength) != 0) {			endpoint->state = DATA_STATE_RECV;			ep0_urb->actual_length = 0;			endpoint->rcv_urb = ep0_urb;                        UDCCSR0 = UDCCSR0_SA | UDCCSR0_OPC;			WMMX_REGS(udccsr0, "     <-- setup recv");			return;		}		retval = usbd_recv_setup(ep0_urb);		if (retval) {			UDCCSR0 = UDCCSR0_FST;			endpoint->state = WAIT_FOR_SETUP;			WMMX_REGS(udccsr0, "    --> bad SETUP FST");		}		if ((ep0_urb->device_request.bmRequestType & 		     USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) {                        UDCCSR0 |= UDCCSR0_IPR;                        WMMX_REGS(UDCCSR0,"      <-- setup nodata");                } else {                        /* Control Read */                        if (!le16_to_cpu(ep0_urb->device_request.wLength)) {				udc_stall_ep(0);				WMMX_REGS(UDCCSR0, "      <-- setup stalling "						   "zero wLength");				return;			}			/* verify that we have non-zero length response */			if (!ep0_urb->actual_length) {				udc_stall_ep (0);				WMMX_REGS(UDCCSR0,"      <-- setup stalling "						  "zero response");				return;			}			endpoint->tx_urb = ep0_urb;			endpoint->sent = 0;			endpoint->last = 0;			endpoint->state = DATA_STATE_XMIT;			wmmx_ep0xmit(endpoint, UDCCSR0);			/* Clear SA and OPR bits */			UDCCSR0 = UDCCSR0_SA | UDCCSR0_OPC;			WMMX_REGS(UDCCSR0,"      <-- setup data");		}	}}static void wmmx_ep0(struct usb_endpoint_instance *endpoint, u32 udccsr0){	int j = 0;	WMMX_REGS(udccsr0,"  --> ep0");	if ((endpoint->state != DATA_STATE_PENDING_XMIT) &&	    (udccsr0 & UDCCSR0_SST)) {		wmmx_ep_reset_interrupt_status(0);		UDCCSR0 |= UDCCSR0_SST;		WMMX_REGS(udccsr0,"  --> ep0 clear SST");		if (endpoint) {			endpoint->state = WAIT_FOR_SETUP;			endpoint->tx_urb = NULL;			endpoint->rcv_urb = NULL;		}		return;	}	if (!endpoint) {		wmmx_ep_reset_interrupt_status(0);		UDCCSR0 |= UDCCSR0_IPR | UDCCSR0_OPC | UDCCSR0_SA;		WMMX_REGS(UDCCSR0,"  ep0 NULL");		return;	}	if (endpoint->tx_urb) {		usbd_tx_complete_irq (endpoint, 0);		if (!endpoint->tx_urb) {			if (endpoint->state != DATA_STATE_NEED_ZLP) {				endpoint->state = WAIT_FOR_OUT_STATUS;                        }                }        }        if ((endpoint->state != DATA_STATE_PENDING_XMIT) &&	    (endpoint->state != WAIT_FOR_SETUP) && 	    (udccsr0 & UDCCSR0_SA)) {		WMMX_REGS(udccsr0,"  --> ep0 early SA");		endpoint->state = WAIT_FOR_SETUP;		endpoint->tx_urb = NULL;		endpoint->rcv_urb = NULL;	}	WMMX_REGS(endpoint->state,"  -- endpoint state");	switch (endpoint->state) {	case DATA_STATE_NEED_ZLP:		UDCCSR0 |= UDCCSR0_IPR;		endpoint->state = WAIT_FOR_OUT_STATUS;		break;	case WAIT_FOR_OUT_STATUS:		if ((udccsr0 & (UDCCSR0_OPC | UDCCSR0_SA)) == UDCCSR0_OPC) {			UDCCSR0 |= UDCCSR0_OPC;		}		WMMX_REGS(UDCCSR0,"  --> ep0 WAIT for STATUS");		endpoint->state = WAIT_FOR_SETUP;        case WAIT_FOR_SETUP:		do {			wmmx_ep0setup(endpoint, UDCCSR0);			if (endpoint->state == DATA_STATE_PENDING_XMIT) {				if (udccsr0 & UDCCSR0_SST) {					wmmx_ep_reset_interrupt_status(0);					UDCCSR0 = UDCCSR0_SST | 						  UDCCSR0_OPC | 						  UDCCSR0_SA;					return;				}				break;			}			if (udccsr0 & UDCCSR0_SST) {				wmmx_ep_reset_interrupt_status(0);				UDCCSR0 |= UDCCSR0_SST |					   UDCCSR0_OPC | 					   UDCCSR0_SA;				WMMX_REGS(udccsr0,"  --> ep0 clear SST");				if (endpoint) {					endpoint->state = WAIT_FOR_SETUP;					endpoint->tx_urb = NULL;					endpoint->rcv_urb = NULL;				}				return;			}			if (j++ > 2) {				u32 udccsr0 = UDCCSR0;                                WMMX_REGS(udccsr0,"  ep0 wait");                                if ((udccsr0 &                                      (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE))                                     == (UDCCSR0_OPC | UDCCSR0_SA)) {                                        UDCCSR0 |= (UDCCSR0_OPC | UDCCSR0_SA);                                        WMMX_REGS(UDCCSR0,"  ep0 force");				} else {					UDCCSR0 |= (UDCCSR0_OPC | UDCCSR0_SA);					WMMX_REGS(UDCCSR0,"  ep0 force and return");					break;				}			}		} while (UDCCSR0 & (UDCCSR0_OPC | UDCCSR0_RNE));		break;	case DATA_STATE_XMIT:		wmmx_ep0xmit(endpoint, UDCCSR0);		break;	case DATA_STATE_PENDING_XMIT:		wmmx_ep0xmit(endpoint, UDCCSR0);	case DATA_STATE_RECV:		wmmx_ep0recv(endpoint, UDCCSR0);		break;        }	wmmx_ep_reset_interrupt_status(0);	WMMX_REGS(endpoint->state,"  -- endpoint state result");	WMMX_REGS(UDCCSR0,"  <-- ep0");}static __inline__ int endpoints_have_interrupt(void){	u32 udcisr0, udcisr1;	udcisr0 = UDCISR0;	udcisr1 = UDCISR1;	if (udcisr0)		return 1;	if (udcisr1)		return 1;	return 0;}/*  *  Bulverde UDC Interrupt Handler */static void wmmx_int_hndlr (int irq, void *dev_id, struct pt_regs *regs){        u32 udcisr0, udcisr1;        int udccr = UDCCR;        int ep;	udc_interrupts++;

⌨️ 快捷键说明

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