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

📄 usb-host.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			nop();			if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {				data = *R_USB_EPT_DATA_ISO;				restore_flags(flags);				if ((IO_MASK(R_USB_EPT_DATA_ISO, valid) & data) &&                                    (IO_EXTRACT(R_USB_EPT_DATA_ISO, dev, data) == devnum) &&                                    (IO_EXTRACT(R_USB_EPT_DATA_ISO, ep, data) == endpoint) &&                                    (IO_EXTRACT(R_USB_EPT_DATA_ISO, max_len, data) == maxlen)) {                                        dbg_epid("Found epid %d for devnum %d, endpoint %d (%s)",                                                 i, devnum, endpoint, out_traffic ? "OUT" : "IN");                                        DBFEXIT;                                        return i;				}			} else {				data = *R_USB_EPT_DATA;				restore_flags(flags);				if ((IO_MASK(R_USB_EPT_DATA, valid) & data) &&				    (IO_EXTRACT(R_USB_EPT_DATA, dev, data) == devnum) &&				    (IO_EXTRACT(R_USB_EPT_DATA, ep, data) == endpoint) &&				    (IO_EXTRACT(R_USB_EPT_DATA, low_speed, data) == slow) &&				    (IO_EXTRACT(R_USB_EPT_DATA, max_len, data) == maxlen)) {						dbg_epid("Found epid %d for devnum %d, endpoint %d (%s)",                                                 i, devnum, endpoint, out_traffic ? "OUT" : "IN");					DBFEXIT;					return i;				}			}		}	}	DBFEXIT;	return -1;}static int etrax_usb_allocate_epid(void){	int i;		DBFENTER;	for (i = 0; i < NBR_OF_EPIDS; i++) {		if (!test_bit(i, (void *)&epid_usage_bitmask)) {			dbg_epid("Found free epid %d", i);			DBFEXIT;			return i;		}	}	dbg_epid("Found no free epids");	DBFEXIT;	return -1;}static int etrax_usb_submit_urb(urb_t *urb){	etrax_hc_t *hc;	int ret = -EINVAL;		DBFENTER;        if (!urb->dev || !urb->dev->bus) {                return -ENODEV;        }	if (urb->next != NULL) {                /* Is it possible for urb to be the head of a list of urbs (via the urb's                   next pointer), used for example in drivers for isochronous traffic.                   I haven't seen a device driver that relies on it being used for submit                   or unlink, so we warn about it and ignore it. */		warn("Urbs are linked, ignoring.");	}        if (urb->timeout) {                /* FIXME. */                warn("urb->timeout specified, ignoring.");        }        	hc = (etrax_hc_t*)urb->dev->bus->hcpriv;		if (usb_pipedevice(urb->pipe) == hc->rh.devnum) {		/* This request is for the Virtual Root Hub. */		ret = etrax_rh_submit_urb(urb);	} else if (usb_pipetype(urb->pipe) == PIPE_BULK) {		ret = etrax_usb_submit_bulk_urb(urb);	} else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {		ret = etrax_usb_submit_ctrl_urb(urb);	} else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {		int bustime;                		if (urb->bandwidth == 0) {			bustime = usb_check_bandwidth(urb->dev, urb);			if (bustime < 0) {				ret = bustime;			} else {				ret = etrax_usb_submit_intr_urb(urb);				if (ret == 0)                                        usb_claim_bandwidth(urb->dev, urb, bustime, 0);			}                } else {                        /* Bandwidth already set. */                        ret = etrax_usb_submit_intr_urb(urb);		}	} else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {                int bustime;        		if (urb->bandwidth == 0) {			bustime = usb_check_bandwidth(urb->dev, urb);			if (bustime < 0) {				ret = bustime;			} else {				ret = etrax_usb_submit_isoc_urb(urb);				if (ret == 0)                                        usb_claim_bandwidth(urb->dev, urb, bustime, 0);			}                } else {                        /* Bandwidth already set. */                        ret = etrax_usb_submit_isoc_urb(urb);		}	}	DBFEXIT;	return ret;}static int etrax_usb_unlink_urb(urb_t *urb){        etrax_hc_t *hc;        etrax_urb_priv_t *urb_priv;        int epid;	DBFENTER;                if (!urb) {                return -EINVAL;        }                if (!urb->dev || !urb->dev->bus) {                return -ENODEV;        }        if (!urb->hcpriv) {                /* This happens if a device driver calls unlink on an urb that                   was never submitted (lazy driver). */                return 0;        }        if (urb->transfer_flags & USB_ASYNC_UNLINK) {                /* FIXME. */                /* If USB_ASYNC_UNLINK is set:                   unlink                   move to a separate urb list                   call complete at next sof with ECONNRESET                                      If not:                   wait 1 ms                   unlink                   call complete with ENOENT                */                warn("USB_ASYNC_UNLINK set, ignoring.");        }                /* One might think that urb->status = -EINPROGRESS would be a requirement for unlinking,           but that doesn't work for interrupt and isochronous traffic since they are completed           repeatedly, and urb->status is set then. That may in itself be a bug though. */        hc = urb->dev->bus->hcpriv;        urb_priv = (etrax_urb_priv_t *)urb->hcpriv;        epid = urb_priv->epid;        /* Set the urb status (synchronous unlink). */        urb->status = -ENOENT;        urb_priv->urb_state = UNLINK;        	if (usb_pipedevice(urb->pipe) == hc->rh.devnum) {		int ret;		ret = etrax_rh_unlink_urb(urb);		DBFEXIT;		return ret;	} else if (usb_pipetype(urb->pipe) == PIPE_BULK) {                dbg_bulk("Unlink of bulk urb (0x%lx)", (unsigned long)urb);                if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) {                        /* The EP was enabled, disable it and wait. */                        TxBulkEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);                                                /* Ah, the luxury of busy-wait. */                        while (*R_DMA_CH8_SUB0_EP == virt_to_phys(&TxBulkEPList[epid]));                }		/* Kicking dummy list out of the party. */		TxBulkEPList[epid].next = virt_to_phys(&TxBulkEPList[(epid + 1) % NBR_OF_EPIDS]);        } else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {                dbg_ctrl("Unlink of ctrl urb (0x%lx)", (unsigned long)urb);                if (TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) {                        /* The EP was enabled, disable it and wait. */                        TxCtrlEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);                                                /* Ah, the luxury of busy-wait. */                        while (*R_DMA_CH8_SUB1_EP == virt_to_phys(&TxCtrlEPList[epid]));                }	} else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {                dbg_intr("Unlink of intr urb (0x%lx)", (unsigned long)urb);                /* Separate function because it's a tad more complicated. */		etrax_usb_unlink_intr_urb(urb);        } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {                dbg_isoc("Unlink of isoc urb (0x%lx)", (unsigned long)urb);                if (TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable)) {                        /* The EP was enabled, disable it and wait. */                        TxIsocEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);                                                /* Ah, the luxury of busy-wait. */                        while (*R_DMA_CH8_SUB3_EP == virt_to_phys(&TxIsocEPList[epid]));                }        }        /* Note that we need to remove the urb from the urb list *before* removing its SB           descriptors. (This means that the isoc eof handler might get a null urb when we           are unlinking the last urb.) */        urb_list_del(urb, epid);        if (usb_pipetype(urb->pipe) == PIPE_BULK) {                TxBulkEPList[epid].sub = 0;                etrax_remove_from_sb_list(urb);        } else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {                TxCtrlEPList[epid].sub = 0;                etrax_remove_from_sb_list(urb);        } else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {                /* Sanity check (should never happen). */                assert(urb_list_empty(epid));                /* Release allocated bandwidth. */                usb_release_bandwidth(urb->dev, urb, 0);        } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {                if (usb_pipeout(urb->pipe)) {                        /* FIXME: If the SB list isn't empty at this point, we need to set up                            the EP descriptor again. */                } else {                        /* For in traffic there is only one SB descriptor for each EP even                           though there may be several urbs (all urbs point at the same SB). */                        if (urb_list_empty(epid)) {                                /* No more urbs, remove the SB. */                                TxIsocEPList[epid].sub = 0;                                etrax_remove_from_sb_list(urb);                        }                }                /* Release allocated bandwidth. */                usb_release_bandwidth(urb->dev, urb, 1);        }                 /* Must be done before calling completion handler. */        kfree(urb_priv);        urb->hcpriv = 0;        if (urb->complete) {                urb->complete(urb);        }        /* Free the epid if urb list is empty. */        if (urb_list_empty(epid)) {                etrax_usb_free_epid(epid);        }        DBFEXIT;        return 0;}static int etrax_usb_get_frame_number(struct usb_device *usb_dev){	DBFENTER;	DBFEXIT;	return (*R_USB_FM_NUMBER & 0x7ff);}static int etrax_usb_allocate_dev(struct usb_device *usb_dev){  	DBFENTER;	DBFEXIT;	return 0;}static int etrax_usb_deallocate_dev(struct usb_device *usb_dev){	DBFENTER;	DBFEXIT;	return 0;}static void etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs){	DBFENTER;        /* This interrupt handler could be used when unlinking EP descriptors. */	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub0_descr)) {		USB_EP_Desc_t *ep;		//dbg_bulk("dma8_sub0_descr (BULK) intr.");		/* It should be safe clearing the interrupt here, since we don't expect to get a new		   one until we restart the bulk channel. */		*R_DMA_CH8_SUB0_CLR_INTR = IO_STATE(R_DMA_CH8_SUB0_CLR_INTR, clr_descr, do);		/* Wait while the DMA is running (though we don't expect it to be). */		while (*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd));		/* Advance the DMA to the next EP descriptor. */		ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB0_EP);		//dbg_bulk("descr intr: DMA is at 0x%lx", (unsigned long)ep);		/* ep->next is already a physical address; no need for a virt_to_phys. */		*R_DMA_CH8_SUB0_EP = ep->next;		/* Start the DMA bulk channel again. */		*R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start);	}	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub1_descr)) {		dbg_ctrl("dma8_sub1_descr (CTRL) intr.");		*R_DMA_CH8_SUB1_CLR_INTR = IO_STATE(R_DMA_CH8_SUB1_CLR_INTR, clr_descr, do);	}	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub2_descr)) {		dbg_intr("dma8_sub2_descr (INTR) intr.");		*R_DMA_CH8_SUB2_CLR_INTR = IO_STATE(R_DMA_CH8_SUB2_CLR_INTR, clr_descr, do);	}	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub3_descr)) {		dbg_isoc("dma8_sub3_descr (ISOC) intr.");		*R_DMA_CH8_SUB3_CLR_INTR = IO_STATE(R_DMA_CH8_SUB3_CLR_INTR, clr_descr, do);	}        	DBFEXIT;}static void etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs){	urb_t *urb;	etrax_urb_priv_t *urb_priv;	int epid = 0;        unsigned long flags;        /* Isoc diagnostics. */        static int curr_fm = 0;        static int prev_fm = 0;        DBFENTER;        /* Clear this interrupt. */	*R_DMA_CH9_CLR_INTR = IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, do);        /* Note that this while loop assumes that all packets span only           one rx descriptor. */        /* The reason we cli here is that we call the driver's callback functions. */        save_flags(flags);        cli(); 	while (myNextRxDesc->status & IO_MASK(USB_IN_status, eop)) {                epid = IO_EXTRACT(USB_IN_status, epid, myNextRxDesc->status);

⌨️ 快捷键说明

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