uhci-debug.c

来自「底层驱动开发」· C语言 代码 · 共 620 行 · 第 1/2 页

C
620
字号
		(usbstat & USBSTS_USBINT) ? "USBINT " : "");	out += sprintf(out, "  usbint    =     %04x\n", usbint);	out += sprintf(out, "  usbfrnum  =   (%d)%03x\n", (usbfrnum >> 10) & 1,		0xfff & (4*(unsigned int)usbfrnum));	out += sprintf(out, "  flbaseadd = %08x\n", flbaseadd);	out += sprintf(out, "  sof       =       %02x\n", sof);	out += uhci_show_sc(1, portsc1, out, len - (out - buf));	out += uhci_show_sc(2, portsc2, out, len - (out - buf));	return out - buf;}static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *buf, int len){	struct list_head *tmp;	char *out = buf;	int count = 0;	if (len < 200)		return 0;	out += sprintf(out, "urb_priv [%p] ", urbp);	out += sprintf(out, "urb [%p] ", urbp->urb);	out += sprintf(out, "qh [%p] ", urbp->qh);	out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe));	out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT"));	switch (usb_pipetype(urbp->urb->pipe)) {	case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO "); break;	case PIPE_INTERRUPT: out += sprintf(out, "INT "); break;	case PIPE_BULK: out += sprintf(out, "BLK "); break;	case PIPE_CONTROL: out += sprintf(out, "CTL "); break;	}	out += sprintf(out, "%s", (urbp->fsbr ? "FSBR " : ""));	out += sprintf(out, "%s", (urbp->fsbr_timeout ? "FSBR_TO " : ""));	if (urbp->urb->status != -EINPROGRESS)		out += sprintf(out, "Status=%d ", urbp->urb->status);	//out += sprintf(out, "Inserttime=%lx ",urbp->inserttime);	//out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime);	count = 0;	list_for_each(tmp, &urbp->td_list)		count++;	out += sprintf(out, "TDs=%d ",count);	if (urbp->queued)		out += sprintf(out, "queued\n");	else {		count = 0;		list_for_each(tmp, &urbp->queue_list)			count++;		out += sprintf(out, "queued URBs=%d\n", count);	}	return out - buf;}static int uhci_show_lists(struct uhci_hcd *uhci, char *buf, int len){	char *out = buf;	struct list_head *head, *tmp;	int count;	out += sprintf(out, "Main list URBs:");	if (list_empty(&uhci->urb_list))		out += sprintf(out, " Empty\n");	else {		out += sprintf(out, "\n");		count = 0;		head = &uhci->urb_list;		tmp = head->next;		while (tmp != head) {			struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);			out += sprintf(out, "  %d: ", ++count);			out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));			tmp = tmp->next;		}	}	out += sprintf(out, "Remove list URBs:");	if (list_empty(&uhci->urb_remove_list))		out += sprintf(out, " Empty\n");	else {		out += sprintf(out, "\n");		count = 0;		head = &uhci->urb_remove_list;		tmp = head->next;		while (tmp != head) {			struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);			out += sprintf(out, "  %d: ", ++count);			out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));			tmp = tmp->next;		}	}	out += sprintf(out, "Complete list URBs:");	if (list_empty(&uhci->complete_list))		out += sprintf(out, " Empty\n");	else {		out += sprintf(out, "\n");		count = 0;		head = &uhci->complete_list;		tmp = head->next;		while (tmp != head) {			struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);			out += sprintf(out, "  %d: ", ++count);			out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));			tmp = tmp->next;		}	}	return out - buf;}static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len){	unsigned long flags;	char *out = buf;	int i, j;	struct uhci_qh *qh;	struct uhci_td *td;	struct list_head *tmp, *head;	spin_lock_irqsave(&uhci->lock, flags);	out += uhci_show_root_hub_state(uhci, out, len - (out - buf));	out += sprintf(out, "HC status\n");	out += uhci_show_status(uhci, out, len - (out - buf));	out += sprintf(out, "Frame List\n");	for (i = 0; i < UHCI_NUMFRAMES; ++i) {		int shown = 0;		td = uhci->fl->frame_cpu[i];		if (!td)			continue;		if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) {			show_frame_num();			out += sprintf(out, "    frame list does not match td->dma_handle!\n");		}		show_frame_num();		head = &td->fl_list;		tmp = head;		do {			td = list_entry(tmp, struct uhci_td, fl_list);			tmp = tmp->next;			out += uhci_show_td(td, out, len - (out - buf), 4);		} while (tmp != head);	}	out += sprintf(out, "Skeleton QH's\n");	for (i = 0; i < UHCI_NUM_SKELQH; ++i) {		int shown = 0;		qh = uhci->skelqh[i];		if (debug > 1) {			show_qh_name();			out += uhci_show_qh(qh, out, len - (out - buf), 4);		}		/* Last QH is the Terminating QH, it's different */		if (i == UHCI_NUM_SKELQH - 1) {			if (qh->link != UHCI_PTR_TERM)				out += sprintf(out, "    bandwidth reclamation on!\n");			if (qh_element(qh) != cpu_to_le32(uhci->term_td->dma_handle))				out += sprintf(out, "    skel_term_qh element is not set to term_td!\n");			continue;		}		j = (i < 7) ? 7 : i+1;		/* Next skeleton */		if (list_empty(&qh->list)) {			if (i < UHCI_NUM_SKELQH - 1) {				if (qh->link !=				    (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) {					show_qh_name();					out += sprintf(out, "    skeleton QH not linked to next skeleton QH!\n");				}			}			continue;		}		show_qh_name();		head = &qh->list;		tmp = head->next;		while (tmp != head) {			qh = list_entry(tmp, struct uhci_qh, list);			tmp = tmp->next;			out += uhci_show_qh(qh, out, len - (out - buf), 4);		}		if (i < UHCI_NUM_SKELQH - 1) {			if (qh->link !=			    (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH))				out += sprintf(out, "    last QH not linked to next skeleton!\n");		}	}	if (debug > 2)		out += uhci_show_lists(uhci, out, len - (out - buf));	spin_unlock_irqrestore(&uhci->lock, flags);	return out - buf;}#define MAX_OUTPUT	(64 * 1024)struct uhci_debug {	int size;	char *data;	struct uhci_hcd *uhci;};static int uhci_debug_open(struct inode *inode, struct file *file){	struct uhci_hcd *uhci = inode->u.generic_ip;	struct uhci_debug *up;	int ret = -ENOMEM;	lock_kernel();	up = kmalloc(sizeof(*up), GFP_KERNEL);	if (!up)		goto out;	up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL);	if (!up->data) {		kfree(up);		goto out;	}	up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);	file->private_data = up;	ret = 0;out:	unlock_kernel();	return ret;}static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence){	struct uhci_debug *up;	loff_t new = -1;	lock_kernel();	up = file->private_data;	switch (whence) {	case 0:		new = off;		break;	case 1:		new = file->f_pos + off;		break;	}	if (new < 0 || new > up->size) {		unlock_kernel();		return -EINVAL;	}	unlock_kernel();	return (file->f_pos = new);}static ssize_t uhci_debug_read(struct file *file, char __user *buf,				size_t nbytes, loff_t *ppos){	struct uhci_debug *up = file->private_data;	return simple_read_from_buffer(buf, nbytes, ppos, up->data, up->size);}static int uhci_debug_release(struct inode *inode, struct file *file){	struct uhci_debug *up = file->private_data;	kfree(up->data);	kfree(up);	return 0;}static struct file_operations uhci_debug_operations = {	.open =		uhci_debug_open,	.llseek =	uhci_debug_lseek,	.read =		uhci_debug_read,	.release =	uhci_debug_release,};#else	/* CONFIG_DEBUG_FS */#define uhci_debug_operations (* (struct file_operations *) NULL)#endif

⌨️ 快捷键说明

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