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

📄 ehci-dbg.c

📁 WiFi IP-Cam solution. FIC8120 platform VIA VT6656 USB Module driver source code.
💻 C
📖 第 1 页 / 共 2 页
字号:
		if ((qh->hw_alt_next & QTD_MASK) == ehci->async->hw_alt_next)
			mark = '#';	/* blocked */
		else if (qh->hw_alt_next & cpu_to_le32 (0x01))
			mark = '.';	/* use hw_qtd_next */
		/* else alt_next points to some other qtd */
	}
	scratch = cpu_to_le32p (&qh->hw_info1);
	hw_curr = (mark == '*') ? cpu_to_le32p (&qh->hw_current) : 0;
	temp = snprintf (next, size,
			"qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
			qh, scratch & 0x007f,
			speed_char (scratch),
			(scratch >> 8) & 0x000f,
			scratch, cpu_to_le32p (&qh->hw_info2),
			cpu_to_le32p (&qh->hw_token), mark,
			(cpu_to_le32 (0x8000000) & qh->hw_token)
				? "data0" : "data1",
			(cpu_to_le32p (&qh->hw_alt_next) >> 1) & 0x0f);
	size -= temp;
	next += temp;

	/* hc may be modifying the list as we read it ... */
	list_for_each (entry, &qh->qtd_list) {
		td = list_entry (entry, struct ehci_qtd, qtd_list);
		scratch = cpu_to_le32p (&td->hw_token);
		mark = ' ';
		if (hw_curr == td->qtd_dma)
			mark = '*';
		else if (qh->hw_qtd_next == td->qtd_dma)
			mark = '+';
		else if (QTD_LENGTH (scratch)) {
			if (td->hw_alt_next == ehci->async->hw_alt_next)
				mark = '#';
			else if (td->hw_alt_next != EHCI_LIST_END)
				mark = '/';
		}
		temp = snprintf (next, size,
				"\n\t%p%c%s len=%d %08x urb %p",
				td, mark, ({ char *tmp;
				 switch ((scratch>>8)&0x03) {
				 case 0: tmp = "out"; break;
				 case 1: tmp = "in"; break;
				 case 2: tmp = "setup"; break;
				 default: tmp = "?"; break;
				 } tmp;}),
				(scratch >> 16) & 0x7fff,
				scratch,
				td->urb);
		if (temp < 0)
			temp = 0;
		else if (size < temp)
			temp = size;
		size -= temp;
		next += temp;
		if (temp == size)
			goto done;
	}

	temp = snprintf (next, size, "\n");
	if (temp < 0)
		temp = 0;
	else if (size < temp)
		temp = size;
	size -= temp;
	next += temp;

done:
	*sizep = size;
	*nextp = next;
}

static ssize_t
show_async (struct device *dev, char *buf)
{
	struct pci_dev		*pdev;
	struct ehci_hcd		*ehci;
	unsigned long		flags;
	unsigned		temp, size;
	char			*next;
	struct ehci_qh		*qh;

	pdev = container_of (dev, struct pci_dev, dev);
	ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd);
	next = buf;
	size = PAGE_SIZE;

	/* dumps a snapshot of the async schedule.
	 * usually empty except for long-term bulk reads, or head.
	 * one QH per line, and TDs we know about
	 */
	spin_lock_irqsave (&ehci->lock, flags);
	for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh)
		qh_lines (ehci, qh, &next, &size);
	if (ehci->reclaim && size > 0) {
		temp = snprintf (next, size, "\nreclaim =\n");
		size -= temp;
		next += temp;

		for (qh = ehci->reclaim; size > 0 && qh; qh = qh->reclaim)
			qh_lines (ehci, qh, &next, &size);
	}
	spin_unlock_irqrestore (&ehci->lock, flags);

	return PAGE_SIZE - size;
}
static DEVICE_ATTR (async, S_IRUGO, show_async, NULL);

#define DBG_SCHED_LIMIT 64

static ssize_t
show_periodic (struct device *dev, char *buf)
{
	struct pci_dev		*pdev;
	struct ehci_hcd		*ehci;
	unsigned long		flags;
	union ehci_shadow	p, *seen;
	unsigned		temp, size, seen_count;
	char			*next;
	unsigned		i, tag;

	if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC)))
		return 0;
	seen_count = 0;

	pdev = container_of (dev, struct pci_dev, dev);
	ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd);
	next = buf;
	size = PAGE_SIZE;

	temp = snprintf (next, size, "size = %d\n", ehci->periodic_size);
	size -= temp;
	next += temp;

	/* dump a snapshot of the periodic schedule.
	 * iso changes, interrupt usually doesn't.
	 */
	spin_lock_irqsave (&ehci->lock, flags);
	for (i = 0; i < ehci->periodic_size; i++) {
		p = ehci->pshadow [i];
		if (!p.ptr)
			continue;
		tag = Q_NEXT_TYPE (ehci->periodic [i]);

		temp = snprintf (next, size, "%4d: ", i);
		size -= temp;
		next += temp;

		do {
			switch (tag) {
			case Q_TYPE_QH:
				temp = snprintf (next, size, " qh%d/%p",
						p.qh->period, p.qh);
				size -= temp;
				next += temp;
				for (temp = 0; temp < seen_count; temp++) {
					if (seen [temp].ptr == p.ptr)
						break;
				}
				/* show more info the first time around */
				if (temp == seen_count) {
					u32	scratch = cpu_to_le32p (
							&p.qh->hw_info1);

					temp = snprintf (next, size,
						" (%cs dev%d ep%d [%d/%d] %d)",
						speed_char (scratch),
						scratch & 0x007f,
						(scratch >> 8) & 0x000f,
						p.qh->usecs, p.qh->c_usecs,
						0x7ff & (scratch >> 16));

					/* FIXME TD info too */

					if (seen_count < DBG_SCHED_LIMIT)
						seen [seen_count++].qh = p.qh;
				} else
					temp = 0;
				tag = Q_NEXT_TYPE (p.qh->hw_next);
				p = p.qh->qh_next;
				break;
			case Q_TYPE_FSTN:
				temp = snprintf (next, size,
					" fstn-%8x/%p", p.fstn->hw_prev,
					p.fstn);
				tag = Q_NEXT_TYPE (p.fstn->hw_next);
				p = p.fstn->fstn_next;
				break;
			case Q_TYPE_ITD:
				temp = snprintf (next, size,
					" itd/%p", p.itd);
				tag = Q_NEXT_TYPE (p.itd->hw_next);
				p = p.itd->itd_next;
				break;
			case Q_TYPE_SITD:
				temp = snprintf (next, size,
					" sitd/%p", p.sitd);
				tag = Q_NEXT_TYPE (p.sitd->hw_next);
				p = p.sitd->sitd_next;
				break;
			}
			size -= temp;
			next += temp;
		} while (p.ptr);

		temp = snprintf (next, size, "\n");
		size -= temp;
		next += temp;
	}
	spin_unlock_irqrestore (&ehci->lock, flags);
	kfree (seen);

	return PAGE_SIZE - size;
}
static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);

#undef DBG_SCHED_LIMIT

static ssize_t
show_registers (struct device *dev, char *buf)
{
	struct pci_dev		*pdev;
	struct ehci_hcd		*ehci;
	unsigned long		flags;
	unsigned		temp, size, i;
	char			*next, scratch [80];
	static char		fmt [] = "%*s\n";
	static char		label [] = "";

	pdev = container_of (dev, struct pci_dev, dev);
	ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd);

	next = buf;
	size = PAGE_SIZE;

	spin_lock_irqsave (&ehci->lock, flags);

	/* Capability Registers */
	i = readw (&ehci->caps->hci_version);
	temp = snprintf (next, size,
		"EHCI %x.%02x, hcd state %d (version " DRIVER_VERSION ")\n",
		i >> 8, i & 0x0ff, ehci->hcd.state);
	size -= temp;
	next += temp;

	// FIXME interpret both types of params
	i = readl (&ehci->caps->hcs_params);
	temp = snprintf (next, size, "structural params 0x%08x\n", i);
	size -= temp;
	next += temp;

	i = readl (&ehci->caps->hcc_params);
	temp = snprintf (next, size, "capability params 0x%08x\n", i);
	size -= temp;
	next += temp;

	/* Operational Registers */
	temp = dbg_status_buf (scratch, sizeof scratch, label,
			readl (&ehci->regs->status));
	temp = snprintf (next, size, fmt, temp, scratch);
	size -= temp;
	next += temp;

	temp = dbg_command_buf (scratch, sizeof scratch, label,
			readl (&ehci->regs->command));
	temp = snprintf (next, size, fmt, temp, scratch);
	size -= temp;
	next += temp;

	temp = dbg_intr_buf (scratch, sizeof scratch, label,
			readl (&ehci->regs->intr_enable));
	temp = snprintf (next, size, fmt, temp, scratch);
	size -= temp;
	next += temp;

	temp = snprintf (next, size, "uframe %04x\n",
			readl (&ehci->regs->frame_index));
	size -= temp;
	next += temp;

	for (i = 0; i < HCS_N_PORTS (ehci->hcs_params); i++) {
		temp = dbg_port_buf (scratch, sizeof scratch, label, i,
				readl (&ehci->regs->port_status [i]));
		temp = snprintf (next, size, fmt, temp, scratch);
		size -= temp;
		next += temp;
	}

	if (ehci->reclaim) {
		temp = snprintf (next, size, "reclaim qh %p%s\n",
				ehci->reclaim,
				ehci->reclaim_ready ? " ready" : "");
		size -= temp;
		next += temp;
	}

#ifdef EHCI_STATS
	temp = snprintf (next, size, "irq normal %ld err %ld reclaim %ld\n",
		ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim);
	size -= temp;
	next += temp;

	temp = snprintf (next, size, "complete %ld unlink %ld\n",
		ehci->stats.complete, ehci->stats.unlink);
	size -= temp;
	next += temp;
#endif

	spin_unlock_irqrestore (&ehci->lock, flags);

	return PAGE_SIZE - size;
}
static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);

static inline void create_debug_files (struct ehci_hcd *bus)
{
	device_create_file (&bus->hcd.pdev->dev, &dev_attr_async);
	device_create_file (&bus->hcd.pdev->dev, &dev_attr_periodic);
	device_create_file (&bus->hcd.pdev->dev, &dev_attr_registers);
}

static inline void remove_debug_files (struct ehci_hcd *bus)
{
	device_remove_file (&bus->hcd.pdev->dev, &dev_attr_async);
	device_remove_file (&bus->hcd.pdev->dev, &dev_attr_periodic);
	device_remove_file (&bus->hcd.pdev->dev, &dev_attr_registers);
}

#endif /* STUB_DEBUG_FILES */

⌨️ 快捷键说明

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