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

📄 usbdcore_mpc8xx.c

📁 U-boot源码 ARM7启动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
				break;			} else if (ret == -2) {				if (usbp->usber & USB_E_TXB) {					usbp->usber |= USB_E_TXB;				}				mpc8xx_udc_flush_tx_fifo (ep);				return -1;			}		};		if (usbp->usber & USB_E_TXB) {			usbp->usber |= USB_E_TXB;		}		/* ACK must be present <= 18bit times from TX */		if (ret == -1) {			continue;		}		/* TX ACK : USB 2.0 8.7.2, Toggle PID, Advance TX */		epi->sent += pkt_len;		epi->last = MIN (urb->actual_length - epi->sent, epi->tx_packetSize);		TOGGLE_TX_PID (ep_ref[ep].pid);		if (epi->sent >= epi->tx_urb->actual_length) {			epi->tx_urb->actual_length = 0;			epi->sent = 0;			if (ep_ref[ep].sc & EP_SEND_ZLP) {				ep_ref[ep].sc &= ~EP_SEND_ZLP;			} else {				return 0;			}		}	}	ERR ("TX fail, endpoint 0x%x tx bytes 0x%x/0x%x\n", ep, epi->sent,	     epi->tx_urb->actual_length);	return -1;}/* mpc8xx_udc_dump_request * * Dump a control request to console */static void mpc8xx_udc_dump_request (struct usb_device_request *request){	DBG ("bmRequestType:%02x bRequest:%02x wValue:%04x "	     "wIndex:%04x wLength:%04x ?\n",	     request->bmRequestType,	     request->bRequest,	     request->wValue, request->wIndex, request->wLength);	return;}/* mpc8xx_udc_ep0_rx_setup * * Decode received ep0 SETUP packet. return non-zero on error */static int mpc8xx_udc_ep0_rx_setup (volatile cbd_t * rx_cbdp){	unsigned int x = 0;	struct urb *purb = ep_ref[0].urb;	struct usb_endpoint_instance *epi =		&udc_device->bus->endpoint_array[0];	for (; x < rx_cbdp->cbd_datlen; x++) {		*(((unsigned char *) &ep_ref[0].urb->device_request) + x) =			*((unsigned char *) (rx_cbdp->cbd_bufaddr + x));	}	mpc8xx_udc_clear_rxbd (rx_cbdp);	if (ep0_recv_setup (purb)) {		mpc8xx_udc_dump_request (&purb->device_request);		return -1;	}	if ((purb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK)	    == USB_REQ_HOST2DEVICE) {		switch (purb->device_request.bRequest) {		case USB_REQ_SET_ADDRESS:			/* Send the Status OUT ZLP */			ep_ref[0].pid = TX_BD_PID_DATA1;			purb->actual_length = 0;			mpc8xx_udc_init_tx (epi, purb);			mpc8xx_udc_ep_tx (epi);			/* Move to the addressed state */			usbp->usaddr = udc_device->address;			mpc8xx_udc_state_transition_up (udc_device->device_state,							STATE_ADDRESSED);			return 0;		case USB_REQ_SET_CONFIGURATION:			if (!purb->device_request.wValue) {				/* Respond at default address */				usbp->usaddr = 0x00;				mpc8xx_udc_state_transition_down (udc_device->device_state,								  STATE_ADDRESSED);			} else {				/* TODO: Support multiple configurations */				mpc8xx_udc_state_transition_up (udc_device->device_state,								STATE_CONFIGURED);				for (x = 1; x < MAX_ENDPOINTS; x++) {					if ((udc_device->bus->endpoint_array[x].endpoint_address & USB_ENDPOINT_DIR_MASK)					    == USB_DIR_IN) {						ep_ref[x].pid = TX_BD_PID_DATA0;					} else {						ep_ref[x].pid = RX_BD_PID_DATA0;					}					/* Set configuration must unstall endpoints */					usbp->usep[x] &= ~STALL_BITMASK;				}			}			break;		default:			/* CDC/Vendor specific */			break;		}		/* Send ZLP as ACK in Status OUT phase */		ep_ref[0].pid = TX_BD_PID_DATA1;		purb->actual_length = 0;		mpc8xx_udc_init_tx (epi, purb);		mpc8xx_udc_ep_tx (epi);	} else {		if (purb->actual_length) {			ep_ref[0].pid = TX_BD_PID_DATA1;			mpc8xx_udc_init_tx (epi, purb);			if (!(purb->actual_length % EP0_MAX_PACKET_SIZE)) {				ep_ref[0].sc |= EP_SEND_ZLP;			}			if (purb->device_request.wValue ==			    USB_DESCRIPTOR_TYPE_DEVICE) {				if (le16_to_cpu (purb->device_request.wLength)				    > purb->actual_length) {					/* Send EP0_MAX_PACKET_SIZE bytes					 * unless correct size requested.					 */					if (purb->actual_length > epi->tx_packetSize) {						purb->actual_length = epi->tx_packetSize;					}				}			}			mpc8xx_udc_ep_tx (epi);		} else {			/* Corrupt SETUP packet? */			ERR ("Zero length data or SETUP with DATA-IN phase ?\n");			return 1;		}	}	return 0;}/* mpc8xx_udc_init_tx * * Setup some basic parameters for a TX transaction */static void mpc8xx_udc_init_tx (struct usb_endpoint_instance *epi,				struct urb *tx_urb){	epi->sent = 0;	epi->last = 0;	epi->tx_urb = tx_urb;}/* mpc8xx_udc_ep0_rx * * Receive ep0/control USB data. Parse and possibly send a response. */static void mpc8xx_udc_ep0_rx (volatile cbd_t * rx_cbdp){	if (rx_cbdp->cbd_sc & RX_BD_PID_SETUP) {		/* Unconditionally accept SETUP packets */		if (mpc8xx_udc_ep0_rx_setup (rx_cbdp)) {			mpc8xx_udc_stall (0);		}	} else {		mpc8xx_udc_clear_rxbd (rx_cbdp);		if ((rx_cbdp->cbd_datlen - 2)) {			/* SETUP with a DATA phase			 * outside of SETUP packet.			 * Reply with STALL.			 */			mpc8xx_udc_stall (0);		}	}}/* mpc8xx_udc_epn_rx * * Receive some data from cbd into USB system urb data abstraction * Upper layers should NAK if there is insufficient RX data space */static int mpc8xx_udc_epn_rx (unsigned int epid, volatile cbd_t * rx_cbdp){	struct usb_endpoint_instance *epi = 0;	struct urb *urb = 0;	unsigned int x = 0;	if (epid >= MAX_ENDPOINTS || !rx_cbdp->cbd_datlen) {		return 0;	}	/* USB 2.0 PDF section 8.6.4	 * Discard data with invalid PID it is a resend.	 */	if (ep_ref[epid].pid != (rx_cbdp->cbd_sc & 0xC0)) {		return 1;	}	TOGGLE_RX_PID (ep_ref[epid].pid);	epi = &udc_device->bus->endpoint_array[epid];	urb = epi->rcv_urb;	for (; x < (rx_cbdp->cbd_datlen - 2); x++) {		*((unsigned char *) (urb->buffer + urb->actual_length + x)) =			*((unsigned char *) (rx_cbdp->cbd_bufaddr + x));	}	if (x) {		usbd_rcv_complete (epi, x, 0);		if (ep_ref[epid].urb->status == RECV_ERROR) {			DBG ("RX error unset NAK\n");			udc_unset_nak (epid);		}	}	return x;}/* mpc8xx_udc_clock_init * * Obtain a clock reference for Full Speed Signaling */static void mpc8xx_udc_clock_init (volatile immap_t * immr,				   volatile cpm8xx_t * cp){#if defined(CFG_USB_EXTC_CLK)	/* This has been tested with a 48MHz crystal on CLK6 */	switch (CFG_USB_EXTC_CLK) {	case 1:		immr->im_ioport.iop_papar |= 0x0100;		immr->im_ioport.iop_padir &= ~0x0100;		cp->cp_sicr |= 0x24;		break;	case 2:		immr->im_ioport.iop_papar |= 0x0200;		immr->im_ioport.iop_padir &= ~0x0200;		cp->cp_sicr |= 0x2D;		break;	case 3:		immr->im_ioport.iop_papar |= 0x0400;		immr->im_ioport.iop_padir &= ~0x0400;		cp->cp_sicr |= 0x36;		break;	case 4:		immr->im_ioport.iop_papar |= 0x0800;		immr->im_ioport.iop_padir &= ~0x0800;		cp->cp_sicr |= 0x3F;		break;	default:		udc_state = STATE_ERROR;		break;	}#elif defined(CFG_USB_BRGCLK)	/* This has been tested with brgclk == 50MHz */	int divisor = 0;	if (gd->cpu_clk < 48000000L) {		ERR ("brgclk is too slow for full-speed USB!\n");		udc_state = STATE_ERROR;		return;	}	/* Assume the brgclk is 'good enough', we want !(gd->cpu_clk%48Mhz)	 * but, can /probably/ live with close-ish alternative rates.	 */	divisor = (gd->cpu_clk / 48000000L) - 1;	cp->cp_sicr &= ~0x0000003F;	switch (CFG_USB_BRGCLK) {	case 1:		cp->cp_brgc1 |= (divisor | CPM_BRG_EN);		cp->cp_sicr &= ~0x2F;		break;	case 2:		cp->cp_brgc2 |= (divisor | CPM_BRG_EN);		cp->cp_sicr |= 0x00000009;		break;	case 3:		cp->cp_brgc3 |= (divisor | CPM_BRG_EN);		cp->cp_sicr |= 0x00000012;		break;	case 4:		cp->cp_brgc4 = (divisor | CPM_BRG_EN);		cp->cp_sicr |= 0x0000001B;		break;	default:		udc_state = STATE_ERROR;		break;	}#else#error "CFG_USB_EXTC_CLK or CFG_USB_BRGCLK must be defined"#endif}/* mpc8xx_udc_cbd_attach * * attach a cbd to and endpoint */static void mpc8xx_udc_cbd_attach (int ep, uchar tx_size, uchar rx_size){	if (!tx_cbd[ep] || !rx_cbd[ep] || ep >= MAX_ENDPOINTS) {		udc_state = STATE_ERROR;		return;	}	if (tx_size > USB_MAX_PKT || rx_size > USB_MAX_PKT ||	    (!tx_size && !rx_size)) {		udc_state = STATE_ERROR;		return;	}	/* Attach CBD to appropiate Parameter RAM Endpoint data structure */	if (rx_size) {		endpoints[ep]->rbase = (u32) rx_cbd[rx_ct];		endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];		rx_ct++;		if (!ep) {			endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];			rx_cbd[rx_ct]->cbd_sc |= RX_BD_W;			rx_ct++;		} else {			rx_ct += 2;			endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct];			rx_cbd[rx_ct]->cbd_sc |= RX_BD_W;			rx_ct++;		}		/* Where we expect to RX data on this endpoint */		ep_ref[ep].prx = rx_cbd[rx_ct - 1];	} else {		ep_ref[ep].prx = 0;		endpoints[ep]->rbase = 0;		endpoints[ep]->rbptr = 0;	}	if (tx_size) {		endpoints[ep]->tbase = (u32) tx_cbd[tx_ct];		endpoints[ep]->tbptr = (u32) tx_cbd[tx_ct];		tx_ct++;	} else {		endpoints[ep]->tbase = 0;		endpoints[ep]->tbptr = 0;	}	endpoints[ep]->tstate = 0;	endpoints[ep]->tbcnt = 0;	endpoints[ep]->mrblr = EP_MAX_PKT;	endpoints[ep]->rfcr = 0x18;	endpoints[ep]->tfcr = 0x18;	ep_ref[ep].sc |= EP_ATTACHED;	DBG ("ep %d rbase 0x%08x rbptr 0x%08x tbase 0x%08x tbptr 0x%08x prx = %p\n",		ep, endpoints[ep]->rbase, endpoints[ep]->rbptr,		endpoints[ep]->tbase, endpoints[ep]->tbptr,		ep_ref[ep].prx);	return;}/* mpc8xx_udc_cbd_init * * Allocate space for a cbd and allocate TX/RX data space */static void mpc8xx_udc_cbd_init (void){	int i = 0;	for (; i < TX_RING_SIZE; i++) {		tx_cbd[i] = (cbd_t *)			mpc8xx_udc_alloc (sizeof (cbd_t), sizeof (int));	}	for (i = 0; i < RX_RING_SIZE; i++) {		rx_cbd[i] = (cbd_t *)			mpc8xx_udc_alloc (sizeof (cbd_t), sizeof (int));	}	for (i = 0; i < TX_RING_SIZE; i++) {		tx_cbd[i]->cbd_bufaddr =			mpc8xx_udc_alloc (EP_MAX_PKT, sizeof (int));		tx_cbd[i]->cbd_sc = (TX_BD_I | TX_BD_W);		tx_cbd[i]->cbd_datlen = 0x0000;	}	for (i = 0; i < RX_RING_SIZE; i++) {		rx_cbd[i]->cbd_bufaddr =			mpc8xx_udc_alloc (EP_MAX_PKT, sizeof (int));		rx_cbd[i]->cbd_sc = (RX_BD_I | RX_BD_E);		rx_cbd[i]->cbd_datlen = 0x0000;	}	return;}/* mpc8xx_udc_endpoint_init * * Attach an endpoint to some dpram */static void mpc8xx_udc_endpoint_init (void){	int i = 0;	for (; i < MAX_ENDPOINTS; i++) {		endpoints[i] = (usb_epb_t *)			mpc8xx_udc_alloc (sizeof (usb_epb_t), 32);	}}/* mpc8xx_udc_alloc * * Grab the address of some dpram */static u32 mpc8xx_udc_alloc (u32 data_size, u32 alignment){	u32 retaddr = address_base;	while (retaddr % alignment) {		retaddr++;	}	address_base += data_size;	return retaddr;}#endif /* CONFIG_MPC885_FAMILY && CONFIG_USB_DEVICE) */

⌨️ 快捷键说明

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