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

📄 usb-host.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	int i;	DBFENTER;        /* Read comment at zout_buffer declaration for an explanation to this. */	TxIntrSB_zout.sw_len = 1;	TxIntrSB_zout.next = 0;	TxIntrSB_zout.buf = virt_to_phys(&zout_buffer[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++) {                CHECK_ALIGN(&TxIntrEPList[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, INVALID_EPID));		TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout);		TxIntrEPList[i].next = virt_to_phys(&TxIntrEPList[i + 1]);	}		CHECK_ALIGN(&TxIntrEPList[i]);	TxIntrEPList[i].hw_len = 0;	TxIntrEPList[i].command =		(IO_STATE(USB_EP_command, eof, yes) |		 IO_STATE(USB_EP_command, eol, yes) |		 IO_STATE(USB_EP_command, enable, yes) |		 IO_FIELD(USB_EP_command, epid, INVALID_EPID));	TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout);	TxIntrEPList[i].next = 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 void init_tx_isoc_ep(void){	int i;		DBFENTER;	        /* Read comment at zout_buffer declaration for an explanation to this. */	TxIsocSB_zout.sw_len = 1;	TxIsocSB_zout.next = 0;	TxIsocSB_zout.buf = virt_to_phys(&zout_buffer[0]);	TxIsocSB_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));		/* The last isochronous EP descriptor is a dummy. */		for (i = 0; i < (NBR_OF_EPIDS - 1); i++) {                CHECK_ALIGN(&TxIsocEPList[i]);		TxIsocEPList[i].hw_len = 0;		TxIsocEPList[i].command = IO_FIELD(USB_EP_command, epid, i);		TxIsocEPList[i].sub = 0;		TxIsocEPList[i].next = virt_to_phys(&TxIsocEPList[i + 1]);	}        CHECK_ALIGN(&TxIsocEPList[i]);	TxIsocEPList[i].hw_len = 0;	/* Must enable the last EP descr to get eof interrupt. */	TxIsocEPList[i].command = (IO_STATE(USB_EP_command, enable, yes) |                                   IO_STATE(USB_EP_command, eof, yes) |                                   IO_STATE(USB_EP_command, eol, yes) |                                   IO_FIELD(USB_EP_command, epid, INVALID_EPID));	TxIsocEPList[i].sub = virt_to_phys(&TxIsocSB_zout);	TxIsocEPList[i].next = virt_to_phys(&TxIsocEPList[0]);	*R_DMA_CH8_SUB3_EP = virt_to_phys(&TxIsocEPList[0]);	*R_DMA_CH8_SUB3_CMD = IO_STATE(R_DMA_CH8_SUB3_CMD, cmd, start);		DBFEXIT;}static void etrax_usb_unlink_intr_urb(urb_t *urb){	volatile USB_EP_Desc_t *first_ep;  /* First EP in the list. */	volatile USB_EP_Desc_t *curr_ep;   /* Current EP, the iterator. */	volatile USB_EP_Desc_t *next_ep;   /* The EP after current. */	volatile USB_EP_Desc_t *unlink_ep; /* The one we should remove from the list. */	int epid;        /* Read 8.8.4 in Designer's Reference, "Removing an EP Descriptor from the List". */	DBFENTER;	epid = ((etrax_urb_priv_t *)urb->hcpriv)->epid;	first_ep = &TxIntrEPList[0];	curr_ep = first_ep;	        /* Note that this loop removes all EP descriptors with this epid. This assumes           that all EP descriptors belong to the one and only urb for this epid. */	do {                next_ep = (USB_EP_Desc_t *)phys_to_virt(curr_ep->next);		if (IO_EXTRACT(USB_EP_command, epid, next_ep->command) == epid) {			dbg_intr("Found EP to unlink for epid %d", epid);                                                /* This is the one we should unlink. */			unlink_ep = next_ep;                        /* Actually unlink the EP from the DMA list. */			curr_ep->next = unlink_ep->next;                        /* Wait until the DMA is no longer at this descriptor. */                        while (*R_DMA_CH8_SUB2_EP == virt_to_phys(unlink_ep));                        /* Now we are free to remove it and its SB descriptor.                           Note that it is assumed here that there is only one sb in the                           sb list for this ep. */			kmem_cache_free(usb_desc_cache, phys_to_virt(unlink_ep->sub));			kmem_cache_free(usb_desc_cache, (USB_EP_Desc_t *)unlink_ep);		}		curr_ep = phys_to_virt(curr_ep->next);			} while (curr_ep != first_ep);}void etrax_usb_do_intr_recover(int epid){	USB_EP_Desc_t *first_ep, *tmp_ep;	DBFENTER;        	first_ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB2_EP);	tmp_ep = first_ep;        /* What this does is simply to walk the list of interrupt           ep descriptors and enable those that are disabled. */ 	do {		if (IO_EXTRACT(USB_EP_command, epid, tmp_ep->command) == epid &&		    !(tmp_ep->command & IO_MASK(USB_EP_command, enable))) {			tmp_ep->command |= IO_STATE(USB_EP_command, enable, yes);		}				tmp_ep = (USB_EP_Desc_t *)phys_to_virt(tmp_ep->next);			} while (tmp_ep != first_ep);        DBFEXIT;}static int etrax_rh_unlink_urb (urb_t *urb){	etrax_hc_t *hc;		DBFENTER;		hc = urb->dev->bus->hcpriv;		if (hc->rh.urb == urb) {		hc->rh.send = 0;		del_timer(&hc->rh.rh_int_timer);	}		DBFEXIT;	return 0;}static void etrax_rh_send_irq(urb_t *urb){	__u16 data = 0;	etrax_hc_t *hc = urb->dev->bus->hcpriv;/*	DBFENTER; *//*  dbg_rh("R_USB_FM_NUMBER   : 0x%08X", *R_USB_FM_NUMBER);  dbg_rh("R_USB_FM_REMAINING: 0x%08X", *R_USB_FM_REMAINING);*/		data |= (hc->rh.wPortChange_1) ? (1 << 1) : 0;	data |= (hc->rh.wPortChange_2) ? (1 << 2) : 0;	*((__u16 *)urb->transfer_buffer) = cpu_to_le16(data);        /* FIXME: Why is actual_length set to 1 when data is 2 bytes?           Since only 1 byte is used, why not declare data as __u8? */	urb->actual_length = 1;	urb->status = 0;		if (data && hc->rh.send && urb->complete) {		dbg_rh("wPortChange_1: 0x%04X", hc->rh.wPortChange_1); 		dbg_rh("wPortChange_2: 0x%04X", hc->rh.wPortChange_2);		urb->complete(urb);	}  /*	DBFEXIT; */}static void etrax_rh_init_int_timer(urb_t *urb){	etrax_hc_t *hc;	/*	DBFENTER; */		hc = urb->dev->bus->hcpriv;	hc->rh.interval = urb->interval;	init_timer(&hc->rh.rh_int_timer);	hc->rh.rh_int_timer.function = etrax_rh_int_timer_do;	hc->rh.rh_int_timer.data = (unsigned long)urb;        /* FIXME: Is the jiffies resolution enough? All intervals < 10 ms will be mapped           to 0, and the rest to the nearest lower 10 ms. */	hc->rh.rh_int_timer.expires = jiffies + ((HZ * hc->rh.interval) / 1000);	add_timer(&hc->rh.rh_int_timer);	/*	DBFEXIT; */}static void etrax_rh_int_timer_do(unsigned long ptr){	urb_t *urb;	etrax_hc_t *hc;	/*	DBFENTER; */		urb = (urb_t*)ptr;	hc = urb->dev->bus->hcpriv;		if (hc->rh.send) {		etrax_rh_send_irq(urb);	}		etrax_rh_init_int_timer(urb);	/*	DBFEXIT; */}static int etrax_usb_setup_epid(urb_t *urb){	int epid;	char devnum, endpoint, out_traffic, slow;	int maxlen;	unsigned long flags;	DBFENTER;		epid = etrax_usb_lookup_epid(urb);	if ((epid != -1)){		/* An epid that fits this urb has been found. */		DBFEXIT;		return epid;	}		/* We must find and initiate a new epid for this urb. */	epid = etrax_usb_allocate_epid();	if (epid == -1) {		/* Failed to allocate a new epid. */		DBFEXIT;		return epid;	}	/* We now have a new epid to use. Initiate it. */	set_bit(epid, (void *)&epid_usage_bitmask);		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));        if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {                /* We want both IN and OUT control traffic to be put on the same EP/SB list. */                out_traffic = 1;        } else {                out_traffic = usb_pipeout(urb->pipe);        }	save_flags(flags);	cli();	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);	nop();	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {		*R_USB_EPT_DATA_ISO = IO_STATE(R_USB_EPT_DATA_ISO, valid, yes) |			/* FIXME: Change any to the actual port? */			IO_STATE(R_USB_EPT_DATA_ISO, port, any) |			IO_FIELD(R_USB_EPT_DATA_ISO, max_len, maxlen) |			IO_FIELD(R_USB_EPT_DATA_ISO, ep, endpoint) |			IO_FIELD(R_USB_EPT_DATA_ISO, dev, devnum);	} else {		*R_USB_EPT_DATA = IO_STATE(R_USB_EPT_DATA, valid, yes) |			IO_FIELD(R_USB_EPT_DATA, low_speed, slow) |			/* FIXME: Change any to the actual port? */			IO_STATE(R_USB_EPT_DATA, port, any) |			IO_FIELD(R_USB_EPT_DATA, max_len, maxlen) |			IO_FIELD(R_USB_EPT_DATA, ep, endpoint) |			IO_FIELD(R_USB_EPT_DATA, dev, devnum);	}			restore_flags(flags);        if (out_traffic) {                set_bit(epid, (void *)&epid_out_traffic);        } else {                clear_bit(epid, (void *)&epid_out_traffic);	}	dbg_epid("Setting up epid %d with devnum %d, endpoint %d and max_len %d (%s)",                 epid, devnum, endpoint, maxlen, out_traffic ? "OUT" : "IN");	DBFEXIT;	return epid;}static void etrax_usb_free_epid(int epid){	unsigned long flags;		DBFENTER;	if (!test_bit(epid, (void *)&epid_usage_bitmask)) {		warn("Trying to free unused epid %d", epid);		DBFEXIT;		return;	}	save_flags(flags);	cli();	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);	nop();	while (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold));        /* This will, among other things, set the valid field to 0. */	*R_USB_EPT_DATA = 0;	restore_flags(flags);	clear_bit(epid, (void *)&epid_usage_bitmask);	dbg_epid("Freed epid %d", epid);		DBFEXIT;}static int etrax_usb_lookup_epid(urb_t *urb){	int i;	__u32 data;	char devnum, endpoint, slow, out_traffic;	int maxlen;	unsigned long flags;	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));        if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {                /* We want both IN and OUT control traffic to be put on the same EP/SB list. */                out_traffic = 1;        } else {                out_traffic = usb_pipeout(urb->pipe);        }        	/* Step through att epids. */	for (i = 0; i < NBR_OF_EPIDS; i++) {		if (test_bit(i, (void *)&epid_usage_bitmask) &&                    test_bit(i, (void *)&epid_out_traffic) == out_traffic) {			save_flags(flags);			cli();			*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, i);

⌨️ 快捷键说明

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