亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? uhci-q.c

?? host usb 主設備程序 支持sd卡 mouse keyboard 的最單單的驅動程序 gcc編譯
?? C
?? 第 1 頁 / 共 4 頁
字號:
/* * Universal Host Controller Interface driver for USB. * * Maintainer: Alan Stern <stern@rowland.harvard.edu> * * (C) Copyright 1999 Linus Torvalds * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com * (C) Copyright 1999 Randy Dunlap * (C) Copyright 1999 Georg Acher, acher@in.tum.de * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu *//* * Technically, updating td->status here is a race, but it's not really a * problem. The worst that can happen is that we set the IOC bit again * generating a spurious interrupt. We could fix this by creating another * QH and leaving the IOC bit always set, but then we would have to play * games with the FSBR code to make sure we get the correct order in all * the cases. I don't think it's worth the effort */static void uhci_set_next_interrupt(struct uhci_hcd *uhci){	if (uhci->is_stopped)		mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);	uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); }static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci){	uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC);}/* * Full-Speed Bandwidth Reclamation (FSBR). * We turn on FSBR whenever a queue that wants it is advancing, * and leave it on for a short time thereafter. */static void uhci_fsbr_on(struct uhci_hcd *uhci){	struct uhci_qh *lqh;	/* The terminating skeleton QH always points back to the first	 * FSBR QH.  Make the last async QH point to the terminating	 * skeleton QH. */	uhci->fsbr_is_on = 1;	lqh = list_entry(uhci->skel_async_qh->node.prev,			struct uhci_qh, node);	lqh->link = LINK_TO_QH(uhci->skel_term_qh);}static void uhci_fsbr_off(struct uhci_hcd *uhci){	struct uhci_qh *lqh;	/* Remove the link from the last async QH to the terminating	 * skeleton QH. */	uhci->fsbr_is_on = 0;	lqh = list_entry(uhci->skel_async_qh->node.prev,			struct uhci_qh, node);	lqh->link = UHCI_PTR_TERM;}static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb){	struct urb_priv *urbp = urb->hcpriv;	if (!(urb->transfer_flags & URB_NO_FSBR))		urbp->fsbr = 1;}static void uhci_urbp_wants_fsbr(struct uhci_hcd *uhci, struct urb_priv *urbp){	if (urbp->fsbr) {		uhci->fsbr_is_wanted = 1;		if (!uhci->fsbr_is_on)			uhci_fsbr_on(uhci);		else if (uhci->fsbr_expiring) {			uhci->fsbr_expiring = 0;			del_timer(&uhci->fsbr_timer);		}	}}static void uhci_fsbr_timeout(unsigned long _uhci){	struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;	unsigned long flags;	spin_lock_irqsave(&uhci->lock, flags);	if (uhci->fsbr_expiring) {		uhci->fsbr_expiring = 0;		uhci_fsbr_off(uhci);	}	spin_unlock_irqrestore(&uhci->lock, flags);}static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci){	dma_addr_t dma_handle;	struct uhci_td *td;	td = dma_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle);	if (!td)		return NULL;	td->dma_handle = dma_handle;	td->frame = -1;	INIT_LIST_HEAD(&td->list);	INIT_LIST_HEAD(&td->fl_list);	return td;}static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td){	if (!list_empty(&td->list))		dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);	if (!list_empty(&td->fl_list))		dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);	dma_pool_free(uhci->td_pool, td, td->dma_handle);}static inline void uhci_fill_td(struct uhci_td *td, u32 status,		u32 token, u32 buffer){	td->status = cpu_to_le32(status);	td->token = cpu_to_le32(token);	td->buffer = cpu_to_le32(buffer);}static void uhci_add_td_to_urbp(struct uhci_td *td, struct urb_priv *urbp){	list_add_tail(&td->list, &urbp->td_list);}static void uhci_remove_td_from_urbp(struct uhci_td *td){	list_del_init(&td->list);}/* * We insert Isochronous URBs directly into the frame list at the beginning */static inline void uhci_insert_td_in_frame_list(struct uhci_hcd *uhci,		struct uhci_td *td, unsigned framenum){	framenum &= (UHCI_NUMFRAMES - 1);	td->frame = framenum;	/* Is there a TD already mapped there? */	if (uhci->frame_cpu[framenum]) {		struct uhci_td *ftd, *ltd;		ftd = uhci->frame_cpu[framenum];		ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);		list_add_tail(&td->fl_list, &ftd->fl_list);		td->link = ltd->link;		wmb();		ltd->link = LINK_TO_TD(td);	} else {		td->link = uhci->frame[framenum];		wmb();		uhci->frame[framenum] = LINK_TO_TD(td);		uhci->frame_cpu[framenum] = td;	}}static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci,		struct uhci_td *td){	/* If it's not inserted, don't remove it */	if (td->frame == -1) {		WARN_ON(!list_empty(&td->fl_list));		return;	}	if (uhci->frame_cpu[td->frame] == td) {		if (list_empty(&td->fl_list)) {			uhci->frame[td->frame] = td->link;			uhci->frame_cpu[td->frame] = NULL;		} else {			struct uhci_td *ntd;			ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);			uhci->frame[td->frame] = LINK_TO_TD(ntd);			uhci->frame_cpu[td->frame] = ntd;		}	} else {		struct uhci_td *ptd;		ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list);		ptd->link = td->link;	}	list_del_init(&td->fl_list);	td->frame = -1;}static inline void uhci_remove_tds_from_frame(struct uhci_hcd *uhci,		unsigned int framenum){	struct uhci_td *ftd, *ltd;	framenum &= (UHCI_NUMFRAMES - 1);	ftd = uhci->frame_cpu[framenum];	if (ftd) {		ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);		uhci->frame[framenum] = ltd->link;		uhci->frame_cpu[framenum] = NULL;		while (!list_empty(&ftd->fl_list))			list_del_init(ftd->fl_list.prev);	}}/* * Remove all the TDs for an Isochronous URB from the frame list */static void uhci_unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb){	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;	struct uhci_td *td;	list_for_each_entry(td, &urbp->td_list, list)		uhci_remove_td_from_frame_list(uhci, td);}static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,		struct usb_device *udev, struct usb_host_endpoint *hep){	dma_addr_t dma_handle;	struct uhci_qh *qh;	qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle);	if (!qh)		return NULL;	memset(qh, 0, sizeof(*qh));	qh->dma_handle = dma_handle;	qh->element = UHCI_PTR_TERM;	qh->link = UHCI_PTR_TERM;	INIT_LIST_HEAD(&qh->queue);	INIT_LIST_HEAD(&qh->node);	if (udev) {		/* Normal QH */		qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;		if (qh->type != USB_ENDPOINT_XFER_ISOC) {			qh->dummy_td = uhci_alloc_td(uhci);			if (!qh->dummy_td) {				dma_pool_free(uhci->qh_pool, qh, dma_handle);				return NULL;			}		}		qh->state = QH_STATE_IDLE;		qh->hep = hep;		qh->udev = udev;		hep->hcpriv = qh;		if (qh->type == USB_ENDPOINT_XFER_INT ||				qh->type == USB_ENDPOINT_XFER_ISOC)			qh->load = usb_calc_bus_time(udev->speed,					usb_endpoint_dir_in(&hep->desc),					qh->type == USB_ENDPOINT_XFER_ISOC,					le16_to_cpu(hep->desc.wMaxPacketSize))				/ 1000 + 1;	} else {		/* Skeleton QH */		qh->state = QH_STATE_ACTIVE;		qh->type = -1;	}	return qh;}static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh){	WARN_ON(qh->state != QH_STATE_IDLE && qh->udev);	if (!list_empty(&qh->queue))		dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh);	list_del(&qh->node);	if (qh->udev) {		qh->hep->hcpriv = NULL;		if (qh->dummy_td)			uhci_free_td(uhci, qh->dummy_td);	}	dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);}/* * When a queue is stopped and a dequeued URB is given back, adjust * the previous TD link (if the URB isn't first on the queue) or * save its toggle value (if it is first and is currently executing). * * Returns 0 if the URB should not yet be given back, 1 otherwise. */static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh,		struct urb *urb){	struct urb_priv *urbp = urb->hcpriv;	struct uhci_td *td;	int ret = 1;	/* Isochronous pipes don't use toggles and their TD link pointers	 * get adjusted during uhci_urb_dequeue().  But since their queues	 * cannot truly be stopped, we have to watch out for dequeues	 * occurring after the nominal unlink frame. */	if (qh->type == USB_ENDPOINT_XFER_ISOC) {		ret = (uhci->frame_number + uhci->is_stopped !=				qh->unlink_frame);		goto done;	}	/* If the URB isn't first on its queue, adjust the link pointer	 * of the last TD in the previous URB.  The toggle doesn't need	 * to be saved since this URB can't be executing yet. */	if (qh->queue.next != &urbp->node) {		struct urb_priv *purbp;		struct uhci_td *ptd;		purbp = list_entry(urbp->node.prev, struct urb_priv, node);		WARN_ON(list_empty(&purbp->td_list));		ptd = list_entry(purbp->td_list.prev, struct uhci_td,				list);		td = list_entry(urbp->td_list.prev, struct uhci_td,				list);		ptd->link = td->link;		goto done;	}	/* If the QH element pointer is UHCI_PTR_TERM then then currently	 * executing URB has already been unlinked, so this one isn't it. */	if (qh_element(qh) == UHCI_PTR_TERM)		goto done;	qh->element = UHCI_PTR_TERM;	/* Control pipes don't have to worry about toggles */	if (qh->type == USB_ENDPOINT_XFER_CONTROL)		goto done;	/* Save the next toggle value */	WARN_ON(list_empty(&urbp->td_list));	td = list_entry(urbp->td_list.next, struct uhci_td, list);	qh->needs_fixup = 1;	qh->initial_toggle = uhci_toggle(td_token(td));done:	return ret;}/* * Fix up the data toggles for URBs in a queue, when one of them * terminates early (short transfer, error, or dequeued). */static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first){	struct urb_priv *urbp = NULL;	struct uhci_td *td;	unsigned int toggle = qh->initial_toggle;	unsigned int pipe;	/* Fixups for a short transfer start with the second URB in the	 * queue (the short URB is the first). */	if (skip_first)		urbp = list_entry(qh->queue.next, struct urb_priv, node);	/* When starting with the first URB, if the QH element pointer is	 * still valid then we know the URB's toggles are okay. */	else if (qh_element(qh) != UHCI_PTR_TERM)		toggle = 2;	/* Fix up the toggle for the URBs in the queue.  Normally this	 * loop won't run more than once: When an error or short transfer	 * occurs, the queue usually gets emptied. */	urbp = list_prepare_entry(urbp, &qh->queue, node);	list_for_each_entry_continue(urbp, &qh->queue, node) {		/* If the first TD has the right toggle value, we don't		 * need to change any toggles in this URB */		td = list_entry(urbp->td_list.next, struct uhci_td, list);		if (toggle > 1 || uhci_toggle(td_token(td)) == toggle) {			td = list_entry(urbp->td_list.prev, struct uhci_td,					list);			toggle = uhci_toggle(td_token(td)) ^ 1;		/* Otherwise all the toggles in the URB have to be switched */		} else {			list_for_each_entry(td, &urbp->td_list, list) {				td->token ^= __constant_cpu_to_le32(							TD_TOKEN_TOGGLE);				toggle ^= 1;			}		}	}	wmb();	pipe = list_entry(qh->queue.next, struct urb_priv, node)->urb->pipe;	usb_settoggle(qh->udev, usb_pipeendpoint(pipe),			usb_pipeout(pipe), toggle);	qh->needs_fixup = 0;}/* * Link an Isochronous QH into its skeleton's list */static inline void link_iso(struct uhci_hcd *uhci, struct uhci_qh *qh){	list_add_tail(&qh->node, &uhci->skel_iso_qh->node);	/* Isochronous QHs aren't linked by the hardware */}/* * Link a high-period interrupt QH into the schedule at the end of its * skeleton's list */static void link_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh){	struct uhci_qh *pqh;	list_add_tail(&qh->node, &uhci->skelqh[qh->skel]->node);	pqh = list_entry(qh->node.prev, struct uhci_qh, node);

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
久久影院午夜片一区| 成人免费一区二区三区视频 | 国产麻豆91精品| 国产精品欧美极品| 色狠狠色噜噜噜综合网| 亚洲国产精品嫩草影院| 日韩欧美三级在线| www.亚洲精品| 国产一区二区女| 亚洲一区二区成人在线观看| 欧美电影免费观看完整版| 成人免费高清视频在线观看| 亚洲第一主播视频| 国产精品欧美久久久久无广告 | 国产激情91久久精品导航| 视频一区欧美日韩| 日韩理论片网站| 国产日韩三级在线| 精品久久久久久久久久久院品网| 91久久精品一区二区三| 成人午夜私人影院| 国产suv精品一区二区6| 激情六月婷婷久久| 蜜桃视频在线观看一区| 亚洲成人先锋电影| 亚洲激情欧美激情| 亚洲国产一区二区视频| 一区二区激情小说| 午夜电影一区二区三区| 婷婷中文字幕一区三区| 亚洲第四色夜色| 免费人成在线不卡| 免费看欧美美女黄的网站| 久久国产三级精品| 久久精品国产秦先生| 久久国产精品一区二区| 国产乱码精品一区二区三区av| 黄色资源网久久资源365| 精品一区二区在线视频| 国产成人激情av| 色中色一区二区| 在线综合视频播放| 国产精品三级电影| 亚洲综合在线第一页| 美脚の诱脚舐め脚责91 | 亚洲欧美电影院| 日本欧美加勒比视频| 国产精品18久久久久久vr| 国产91富婆露脸刺激对白| 色婷婷国产精品久久包臀| 精品国产一区二区国模嫣然| 国产精品久久久久婷婷二区次| 亚洲第一福利一区| 91激情五月电影| 国产精品美女久久久久久2018| 狠狠色狠狠色综合| 欧美日韩国产一区| 亚洲精品国产一区二区精华液| 国产精品一级片在线观看| 欧美精品成人一区二区三区四区| 国产精品乱码一区二区三区软件| 麻豆国产一区二区| 欧美一级高清大全免费观看| 亚洲第一狼人社区| 欧美综合天天夜夜久久| 综合久久久久久| 99久久免费视频.com| 中文字幕欧美激情一区| 国产成人午夜片在线观看高清观看| 日韩一区二区影院| 美腿丝袜一区二区三区| 欧美成人a在线| 春色校园综合激情亚洲| 欧美高清在线一区| 丁香婷婷综合网| 亚洲精品视频在线观看免费| 欧美性色aⅴ视频一区日韩精品| 亚洲第一搞黄网站| 日韩精品中午字幕| proumb性欧美在线观看| 天天综合色天天| 日本一区二区免费在线观看视频| 高清beeg欧美| 天堂成人国产精品一区| 久久欧美中文字幕| 在线免费亚洲电影| 免费的国产精品| 亚洲欧美福利一区二区| 2020国产精品自拍| 日本道精品一区二区三区 | 亚洲电影一级片| 国产欧美日韩久久| 日韩欧美中文字幕制服| 91丨九色porny丨蝌蚪| 久久99久久久久久久久久久| 中文字幕亚洲区| 精品美女在线观看| 正在播放一区二区| 欧美久久久久久久久| 99vv1com这只有精品| 国产在线精品不卡| 黑人精品欧美一区二区蜜桃 | 日韩精品视频网| 一区二区三区.www| 日韩伦理电影网| 日韩一区欧美一区| 国产精品看片你懂得| ㊣最新国产の精品bt伙计久久| 欧美精品v日韩精品v韩国精品v| 91亚洲精品久久久蜜桃| 国产成人三级在线观看| 国产久卡久卡久卡久卡视频精品| 麻豆国产精品视频| 久久不见久久见中文字幕免费| 亚洲国产视频一区| 日本美女一区二区三区视频| 青青青爽久久午夜综合久久午夜| 亚洲一区在线电影| 日本色综合中文字幕| 韩国欧美国产一区| 91蜜桃免费观看视频| 欧美日韩一二三区| 国产三级精品三级| 中文字幕亚洲一区二区av在线| 亚洲一区二区四区蜜桃| 乱中年女人伦av一区二区| 成人激情免费网站| 欧美久久婷婷综合色| 久久久www成人免费毛片麻豆| 国产精品丝袜久久久久久app| 亚洲乱码一区二区三区在线观看| 亚洲电影视频在线| 精品一区二区三区免费观看| 丁香另类激情小说| 51午夜精品国产| 一区二区三区在线视频播放| 久久国产婷婷国产香蕉| 91丨九色丨蝌蚪丨老版| 国产性色一区二区| 日韩成人精品在线观看| 97se狠狠狠综合亚洲狠狠| 久久美女高清视频| 狠狠色丁香婷婷综合| 欧美美女bb生活片| 亚洲精品国产一区二区三区四区在线| 国产精品综合视频| 欧美精品一区二区蜜臀亚洲| 亚洲第一搞黄网站| 91黄色免费网站| 亚洲一区二区中文在线| 在线观看网站黄不卡| 一区二区三区四区精品在线视频| www.色综合.com| 亚洲色图19p| 欧美视频在线观看一区二区| 亚洲丰满少妇videoshd| 在线观看网站黄不卡| 亚洲一二三四区| 欧美日韩色一区| 国内精品伊人久久久久影院对白| 久久亚洲一区二区三区明星换脸| 免费欧美日韩国产三级电影| 欧美成人aa大片| 国产成人在线视频播放| 亚洲免费毛片网站| 5566中文字幕一区二区电影 | 美女看a上一区| 中文字幕乱码亚洲精品一区| 91在线精品秘密一区二区| 亚洲一区二区三区四区的| 日韩丝袜美女视频| 成+人+亚洲+综合天堂| 日韩综合一区二区| 国产精品视频九色porn| 制服丝袜亚洲播放| 色综合久久中文字幕综合网| 另类综合日韩欧美亚洲| 亚洲日本欧美天堂| 精品欧美久久久| 日韩午夜精品电影| 欧美性xxxxxxxx| 国产电影精品久久禁18| 日本va欧美va欧美va精品| 亚洲欧美韩国综合色| 国产欧美精品一区二区色综合朱莉| 在线观看日韩国产| 91性感美女视频| 99视频一区二区| 成人动漫中文字幕| 国精产品一区一区三区mba桃花| 午夜精品福利在线| 午夜日韩在线观看| 亚洲福利一区二区| 一区二区三区四区五区视频在线观看| 久久亚洲春色中文字幕久久久| 欧美日韩中文字幕一区| 欧美无砖专区一中文字| 91精品婷婷国产综合久久竹菊| 欧美色国产精品| 在线播放亚洲一区|