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

📄 usb-host.c

📁 广州斯道2410普及版II的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * usb-host.c: ETRAX 100LX USB Host Controller Driver (HCD) * * Copyright (c) 2001 Axis Communications AB. * * $Id: usb-host.c,v 1.13 2001/11/13 12:06:17 pkj Exp $ * */#include <linux/config.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/ioport.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/unistd.h>#include <linux/interrupt.h>#include <linux/init.h>#include <linux/version.h>#include <linux/list.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/dma.h>#include <asm/system.h>#include <asm/svinto.h>#include <linux/usb.h>#include "usb-host.h"#define ETRAX_USB_HC_IRQ USB_HC_IRQ_NBR#define ETRAX_USB_RX_IRQ USB_DMA_RX_IRQ_NBR#define ETRAX_USB_TX_IRQ USB_DMA_TX_IRQ_NBRstatic const char *usb_hcd_version = "$Revision: 1.13 $";#undef KERN_DEBUG#define KERN_DEBUG ""#undef USB_DEBUG_RH#undef USB_DEBUG_EP#undef USB_DEBUG_DESC#undef USB_DEBUG_TRACE#undef USB_DEBUG_CTRL#undef USB_DEBUG_BULK#undef USB_DEBUG_INTR#ifdef USB_DEBUG_RH#define dbg_rh(format, arg...) printk(KERN_DEBUG __FILE__ ": (RH) " format "\n" , ## arg)#else#define dbg_rh(format, arg...) do {} while (0)#endif#ifdef USB_DEBUG_EP#define dbg_ep(format, arg...) printk(KERN_DEBUG __FILE__ ": (EP) " format "\n" , ## arg)#else#define dbg_ep(format, arg...) do {} while (0)#endif#ifdef USB_DEBUG_CTRL#define dbg_ctrl(format, arg...) printk(KERN_DEBUG __FILE__ ": (CTRL) " format "\n" , ## arg)#else#define dbg_ctrl(format, arg...) do {} while (0)#endif#ifdef USB_DEBUG_BULK#define dbg_bulk(format, arg...) printk(KERN_DEBUG __FILE__ ": (BULK) " format "\n" , ## arg)#else#define dbg_bulk(format, arg...) do {} while (0)#endif#ifdef USB_DEBUG_INTR#define dbg_intr(format, arg...) printk(KERN_DEBUG __FILE__ ": (INTR) " format "\n" , ## arg)#else#define dbg_intr(format, arg...) do {} while (0)#endif#ifdef USB_DEBUG_TRACE#define DBFENTER (printk(KERN_DEBUG __FILE__ ": Entering: " __FUNCTION__ "\n"))#define DBFEXIT  (printk(KERN_DEBUG __FILE__ ": Exiting:  " __FUNCTION__ "\n"))#else#define DBFENTER do {} while (0)#define DBFEXIT  do {} while (0)#endif/*------------------------------------------------------------------- Virtual Root Hub -------------------------------------------------------------------*/static __u8 root_hub_dev_des[] ={	0x12,  /*  __u8  bLength; */	0x01,  /*  __u8  bDescriptorType; Device */	0x00,  /*  __u16 bcdUSB; v1.0 */	0x01,	0x09,  /*  __u8  bDeviceClass; HUB_CLASSCODE */	0x00,  /*  __u8  bDeviceSubClass; */	0x00,  /*  __u8  bDeviceProtocol; */	0x08,  /*  __u8  bMaxPacketSize0; 8 Bytes */	0x00,  /*  __u16 idVendor; */	0x00,	0x00,  /*  __u16 idProduct; */	0x00,	0x00,  /*  __u16 bcdDevice; */	0x00,	0x00,  /*  __u8  iManufacturer; */	0x02,  /*  __u8  iProduct; */	0x01,  /*  __u8  iSerialNumber; */	0x01   /*  __u8  bNumConfigurations; */};/* Configuration descriptor */static __u8 root_hub_config_des[] ={	0x09,  /*  __u8  bLength; */	0x02,  /*  __u8  bDescriptorType; Configuration */	0x19,  /*  __u16 wTotalLength; */	0x00,	0x01,  /*  __u8  bNumInterfaces; */	0x01,  /*  __u8  bConfigurationValue; */	0x00,  /*  __u8  iConfiguration; */	0x40,  /*  __u8  bmAttributes; Bit 7: Bus-powered */	0x00,  /*  __u8  MaxPower; */     /* interface */	0x09,  /*  __u8  if_bLength; */	0x04,  /*  __u8  if_bDescriptorType; Interface */	0x00,  /*  __u8  if_bInterfaceNumber; */	0x00,  /*  __u8  if_bAlternateSetting; */	0x01,  /*  __u8  if_bNumEndpoints; */	0x09,  /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */	0x00,  /*  __u8  if_bInterfaceSubClass; */	0x00,  /*  __u8  if_bInterfaceProtocol; */	0x00,  /*  __u8  if_iInterface; */     /* endpoint */	0x07,  /*  __u8  ep_bLength; */	0x05,  /*  __u8  ep_bDescriptorType; Endpoint */	0x81,  /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */	0x03,  /*  __u8  ep_bmAttributes; Interrupt */	0x08,  /*  __u16 ep_wMaxPacketSize; 8 Bytes */	0x00,	0xff   /*  __u8  ep_bInterval; 255 ms */};static __u8 root_hub_hub_des[] ={	0x09,  /*  __u8  bLength; */	0x29,  /*  __u8  bDescriptorType; Hub-descriptor */	0x02,  /*  __u8  bNbrPorts; */	0x00,  /* __u16  wHubCharacteristics; */	0x00,	0x01,  /*  __u8  bPwrOn2pwrGood; 2ms */	0x00,  /*  __u8  bHubContrCurrent; 0 mA */	0x00,  /*  __u8  DeviceRemovable; *** 7 Ports max *** */	0xff   /*  __u8  PortPwrCtrlMask; *** 7 ports max *** */};#define OK(x) len = (x); dbg_rh("OK(%d): line: %d", x, __LINE__); break#define CHECK_ALIGN(x) if (((__u32)(x)) & 0x00000003) \{panic("Alignment check (DWORD) failed at %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);}static unsigned long submit_urb_count = 0;//#define ETRAX_USB_INTR_IRQ//#define ETRAX_USB_INTR_ERROR_FATAL#define RX_BUF_SIZE        32768#define RX_DESC_BUF_SIZE   64#define NBR_OF_RX_DESC     (RX_BUF_SIZE / RX_DESC_BUF_SIZE)#define NBR_OF_EP_DESC     32#define MAX_INTR_INTERVAL 128static __u32 ep_usage_bitmask;static __u32 ep_really_active;static __u32 ep_out_traffic;static unsigned char RxBuf[RX_BUF_SIZE];static USB_IN_Desc_t RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned (4)));static volatile USB_IN_Desc_t *myNextRxDesc;static volatile USB_IN_Desc_t *myLastRxDesc;static volatile USB_IN_Desc_t *myPrevRxDesc;static USB_EP_Desc_t TxCtrlEPList[NBR_OF_EP_DESC] __attribute__ ((aligned (4)));static USB_EP_Desc_t TxBulkEPList[NBR_OF_EP_DESC] __attribute__ ((aligned (4)));static USB_EP_Desc_t TxIntrEPList[MAX_INTR_INTERVAL] __attribute__ ((aligned (4)));static USB_SB_Desc_t TxIntrSB_zout __attribute__ ((aligned (4)));static urb_t *URB_List[NBR_OF_EP_DESC];static kmem_cache_t *usb_desc_cache;static struct usb_bus *etrax_usb_bus;#ifdef USB_DEBUG_DESCstatic void dump_urb (purb_t purb);#endifstatic void init_rx_buffers(void);static int etrax_rh_unlink_urb (urb_t *urb);static void etrax_rh_send_irq(urb_t *urb);static void etrax_rh_init_int_timer(urb_t *urb);static void etrax_rh_int_timer_do(unsigned long ptr);static void etrax_usb_setup_epid(int epid, char devnum, char endpoint,				 char packsize, char slow, char out_traffic);static int etrax_usb_lookup_epid(unsigned char devnum, char endpoint,				 char slow, int maxp, char out_traffic);static int etrax_usb_allocate_epid(void);static void etrax_usb_free_epid(int epid);static void cleanup_sb(USB_SB_Desc_t *sb);static void etrax_usb_do_ctrl_hw_add(urb_t *urb, int epid, char maxlen);static void etrax_usb_do_bulk_hw_add(urb_t *urb, int epid, char maxlen);static int etrax_usb_submit_ctrl_urb(urb_t *urb);static int etrax_usb_submit_urb(urb_t *urb);static int etrax_usb_unlink_urb(urb_t *urb);static int etrax_usb_get_frame_number(struct usb_device *usb_dev);static int etrax_usb_allocate_dev(struct usb_device *usb_dev);static int etrax_usb_deallocate_dev(struct usb_device *usb_dev);static void etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs);static void etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs);static void etrax_usb_hc_intr_top_half(int irq, void *vhc, struct pt_regs *regs);static int etrax_rh_submit_urb (urb_t *urb);static int etrax_usb_hc_init(void);static void etrax_usb_hc_cleanup(void);static struct usb_operations etrax_usb_device_operations ={	etrax_usb_allocate_dev,	etrax_usb_deallocate_dev,	etrax_usb_get_frame_number,	etrax_usb_submit_urb,	etrax_usb_unlink_urb};#ifdef USB_DEBUG_DESCstatic void dump_urb(purb_t purb){	printk("\nurb                   :0x%08X\n", purb);	printk("next                  :0x%08X\n", purb->next);	printk("dev                   :0x%08X\n", purb->dev);	printk("pipe                  :0x%08X\n", purb->pipe);	printk("status                :%d\n", purb->status);	printk("transfer_flags        :0x%08X\n", purb->transfer_flags);	printk("transfer_buffer       :0x%08X\n", purb->transfer_buffer);	printk("transfer_buffer_length:%d\n", purb->transfer_buffer_length);	printk("actual_length         :%d\n", purb->actual_length);	printk("setup_packet          :0x%08X\n", purb->setup_packet);	printk("start_frame           :%d\n", purb->start_frame);	printk("number_of_packets     :%d\n", purb->number_of_packets);	printk("interval              :%d\n", purb->interval);	printk("error_count           :%d\n", purb->error_count);	printk("context               :0x%08X\n", purb->context);	printk("complete              :0x%08X\n\n", purb->complete);}static void dump_in_desc(USB_IN_Desc_t *in){	printk("\nUSB_IN_Desc at 0x%08X\n", in);	printk("  sw_len  : 0x%04X (%d)\n", in->sw_len, in->sw_len);	printk("  command : 0x%04X\n", in->command);	printk("  next    : 0x%08X\n", in->next);	printk("  buf     : 0x%08X\n", in->buf);	printk("  hw_len  : 0x%04X (%d)\n", in->hw_len, in->hw_len);	printk("  status  : 0x%04X\n\n", in->status);}static void dump_sb_desc(USB_SB_Desc_t *sb){	printk("\nUSB_SB_Desc at 0x%08X\n", sb);	printk("  sw_len  : 0x%04X (%d)\n", sb->sw_len, sb->sw_len);	printk("  command : 0x%04X\n", sb->command);	printk("  next    : 0x%08X\n", sb->next);	printk("  buf     : 0x%08X\n\n", sb->buf);}static void dump_ep_desc(USB_EP_Desc_t *ep){	printk("\nUSB_EP_Desc at 0x%08X\n", ep);	printk("  hw_len  : 0x%04X (%d)\n", ep->hw_len, ep->hw_len);	printk("  command : 0x%08X\n", ep->command);	printk("  sub     : 0x%08X\n", ep->sub);	printk("  nep     : 0x%08X\n\n", ep->nep);}#else#define dump_urb(...)     do {} while (0)#define dump_in_desc(...) do {} while (0)#define dump_sb_desc(...) do {} while (0)#define dump_ep_desc(...) do {} while (0)#endifstatic void init_rx_buffers(void){	int i;		DBFENTER;		for (i = 0; i < (NBR_OF_RX_DESC - 1); i++) {		RxDescList[i].sw_len = RX_DESC_BUF_SIZE;		RxDescList[i].command = 0;		RxDescList[i].next = virt_to_phys(&RxDescList[i + 1]);		RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE));		RxDescList[i].hw_len = 0;		RxDescList[i].status = 0;	}		RxDescList[i].sw_len = RX_DESC_BUF_SIZE;	RxDescList[i].command = IO_STATE(USB_IN_command, eol, yes);	RxDescList[i].next = virt_to_phys(&RxDescList[0]);	RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE));	RxDescList[i].hw_len = 0;	RxDescList[i].status = 0;	myNextRxDesc = &RxDescList[0];	myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];	myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];	*R_DMA_CH9_FIRST = virt_to_phys(myNextRxDesc);	*R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, start);		DBFEXIT;}static void init_tx_ctrl_ep(void){	int i;		DBFENTER;		for (i = 0; i < (NBR_OF_EP_DESC - 1); i++) {		TxCtrlEPList[i].hw_len = 0;		TxCtrlEPList[i].command = IO_FIELD(USB_EP_command, epid, i);		TxCtrlEPList[i].sub = 0;		TxCtrlEPList[i].nep = virt_to_phys(&TxCtrlEPList[i + 1]);	}		TxCtrlEPList[i].hw_len = 0;	TxCtrlEPList[i].command = IO_STATE(USB_EP_command, eol, yes) |		IO_FIELD(USB_EP_command, epid, i);	TxCtrlEPList[i].sub = 0;	TxCtrlEPList[i].nep = virt_to_phys(&TxCtrlEPList[0]);		*R_DMA_CH8_SUB1_EP = virt_to_phys(&TxCtrlEPList[0]);	*R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB1_CMD, cmd, start);		DBFEXIT;}static void init_tx_bulk_ep(void){	int i;		DBFENTER;		for (i = 0; i < (NBR_OF_EP_DESC - 1); i++) {		TxBulkEPList[i].hw_len = 0;		TxBulkEPList[i].command = IO_FIELD(USB_EP_command, epid, i);		TxBulkEPList[i].sub = 0;		TxBulkEPList[i].nep = virt_to_phys(&TxBulkEPList[i + 1]);	}		TxBulkEPList[i].hw_len = 0;	TxBulkEPList[i].command = IO_STATE(USB_EP_command, eol, yes) |		IO_FIELD(USB_EP_command, epid, i);	TxBulkEPList[i].sub = 0;	TxBulkEPList[i].nep = virt_to_phys(&TxBulkEPList[0]);		*R_DMA_CH8_SUB0_EP = virt_to_phys(&TxBulkEPList[0]);	*R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start);		DBFEXIT;}static void init_tx_intr_ep(void){	int i;	DBFENTER;	TxIntrSB_zout.sw_len = 0;	TxIntrSB_zout.next = 0;	TxIntrSB_zout.buf = 0;	TxIntrSB_zout.command = IO_FIELD(USB_SB_command, rem, 0) |		IO_STATE(USB_SB_command, tt, zout) |		IO_STATE(USB_SB_command, full, yes) |		IO_STATE(USB_SB_command, eot, yes) |		IO_STATE(USB_SB_command, eol, yes);	for (i = 0; i < (MAX_INTR_INTERVAL - 1); i++) {		TxIntrEPList[i].hw_len = 0;		TxIntrEPList[i].command = IO_STATE(USB_EP_command, eof, yes) |			IO_STATE(USB_EP_command, enable, yes) |			IO_FIELD(USB_EP_command, epid, 0);		TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout);		TxIntrEPList[i].nep = virt_to_phys(&TxIntrEPList[i + 1]);	}		TxIntrEPList[i].hw_len = 0;	TxIntrEPList[i].command =		IO_STATE(USB_EP_command, eof, yes) |		IO_STATE(USB_EP_command, enable, yes) |		IO_FIELD(USB_EP_command, epid, 0);	TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout);	TxIntrEPList[i].nep = virt_to_phys(&TxIntrEPList[0]);	*R_DMA_CH8_SUB2_EP = virt_to_phys(&TxIntrEPList[0]);	*R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start);		DBFEXIT;}static int etrax_usb_unlink_intr_urb(urb_t *urb){	USB_EP_Desc_t *tmp_ep;	USB_EP_Desc_t *first_ep;		USB_EP_Desc_t *ep_desc;		int epid;	char devnum;	char endpoint;	char slow;	int maxlen;	char out_traffic;	int i;		DBFENTER;	devnum = usb_pipedevice(urb->pipe);	endpoint = usb_pipeendpoint(urb->pipe);	slow = usb_pipeslow(urb->pipe);	maxlen = usb_maxpacket(urb->dev, urb->pipe,			       usb_pipeout(urb->pipe));	out_traffic = usb_pipeout(urb->pipe);	epid = etrax_usb_lookup_epid(devnum, endpoint, slow, maxlen, out_traffic);	if (epid == -1) {		err("Trying to unlink urb that is not in traffic queue!!");		return -1;  /* fix this */	}	*R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, stop);	/* Somehow wait for the DMA to finish current activities */	i = jiffies + 100;	while (jiffies < i);			first_ep = &TxIntrEPList[0];	tmp_ep = first_ep;		do {		if (IO_EXTRACT(USB_EP_command, epid, ((USB_EP_Desc_t *)phys_to_virt(tmp_ep->nep))->command)		    == epid) {			/* Unlink it !!! */			dbg_intr("Found urb to unlink for epid %d", epid);						ep_desc = phys_to_virt(tmp_ep->nep);			tmp_ep->nep = ep_desc->nep;			kmem_cache_free(usb_desc_cache, phys_to_virt(ep_desc->sub));			kmem_cache_free(usb_desc_cache, ep_desc);		}		tmp_ep = phys_to_virt(tmp_ep->nep);			} while (tmp_ep != first_ep);	/* We should really try to move the EP register to an EP that is not removed	   instead of restarting, but this will work too */	*R_DMA_CH8_SUB2_EP = virt_to_phys(&TxIntrEPList[0]);	*R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start);

⌨️ 快捷键说明

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