📄 m8xxhci.c
字号:
count = e_wrapped ? MAX_EVENTS : e_count; for (i = 0; i < count; i++) events_copy[i] = events[i]; e_count = 0; e_wrapped = 0; events_copy_count = count; spin_unlock_irqrestore(&event_lock, flags);}static char *text_port_state(int state){ switch (state) { case PS_INIT: return "init"; case PS_DISCONNECTED: return "disconnected"; case PS_CONNECTED: return "connected"; case PS_READY: return "ready"; case PS_MISSING: return "missing"; } return "unknown";}static char *text_port_status(char *buf, int status){ char *p = buf; *p = 0; if (status & RH_PS_CCS) p += sprintf(p, "CCS "); if (status & RH_PS_PES) p += sprintf(p, "PES "); if (status & RH_PS_PSS) p += sprintf(p, "PSS "); if (status & RH_PS_PRS) p += sprintf(p, "PRS "); if (status & RH_PS_PPS) p += sprintf(p, "PPS "); if (status & RH_PS_LSDA) p += sprintf(p, "LSDA "); if (status & RH_PS_CSC) p += sprintf(p, "CDC "); if (status & RH_PS_PESC) p += sprintf(p, "PESC "); if (status & RH_PS_PSSC) p += sprintf(p, "PSSC "); if (status & RH_PS_PRSC) p += sprintf(p, "PRSC "); return buf;}static intusb_proc_log_infos(char *buffer, int *len, off_t *begin, off_t offset, int size){ int i; if (offset == 0) { usb_proc_snapshot_events(); logging_on(); } PRINT_PROC("USB event log:\n"); PRINT_PROC("event count %d\n", events_copy_count); for (i = 0; i < events_copy_count; i++) { u_long t1, t2; t1 = events_copy[i].e_time >> 32; t2 = events_copy[i].e_time; PRINT_PROC("%08x:%08x %s %d (0x%x)\n", (int)t1, (int)t2, events_copy[i].e_str, events_copy[i].e_num, events_copy[i].e_num); } return 1;}static intusb_proc_infos(char *buffer, int *len, off_t *begin, off_t offset, int size){ struct m8xxhci_private *hp = (struct m8xxhci_private *)m8xxhci_ptr; char buf[32]; unsigned long flags; PRINT_PROC("USB host controller v%d.%d:\n", M8XXHCI_HCI_VERS >> 8, M8XXHCI_HCI_VERS & 0xff); PRINT_PROC("controller %senabled\n", controller_enabled() ? "" : "not "); PRINT_PROC("root hub port state %s, status %s\n", text_port_state(hp->port_state), text_port_status(buf, hp->rh.port_status));#ifdef DEBUG_CONNECT { volatile immap_t *immap = (immap_t *)IMAP_ADDR; struct m8xxhci_private *hp = (struct m8xxhci_private *)m8xxhci_ptr; volatile usbregs_t *usbregs = hp->usbregs; PRINT_PROC("oe %d; bus %d%d idle %d\n", immap->im_ioport.iop_padat & PA_USB_OE ? 1 : 0, immap->im_ioport.iop_pcdat & PC_USB_RXP ? 1 : 0, immap->im_ioport.iop_pcdat & PC_USB_RXN ? 1 : 0, usbregs->usb_usbs ? 1 : 0); }#endif PRINT_PROC("ints: cpm %lu, timer %lu, isrs %lu\n", hp->stats.cpm_interrupts, hp->stats.tmr_interrupts, hp->stats.isrs); PRINT_PROC(" idle %lu, rst %lu, bsy %lu, rxb %lu, txb %lu\n", hp->stats.idle, hp->stats.reset, hp->stats.bsy, hp->stats.rxb, hp->stats.txb); PRINT_PROC("errs: tx0 %lu, timeout %lu, underrun %lu\n", hp->stats.txe[0], hp->stats.tx_to, hp->stats.tx_un); PRINT_PROC(" rx %lu, nak %lu, stall %lu, mismatch %lu\n", hp->stats.rx_err, hp->stats.tx_nak, hp->stats.tx_stal, hp->stats.rx_mismatch); PRINT_PROC("comp: iso %lu, intr %lu, ctrl %lu, bulk %lu\n", hp->stats.completes[0], hp->stats.completes[1], hp->stats.completes[2], hp->stats.completes[3]); PRINT_PROC("root hub sends %lu\n", hp->stats.rh_send_irqs); PRINT_PROC("retransmits %lu\n", hp->stats.retransmit); PRINT_PROC("tx restarts %lu\n", hp->stats.tx_restart); PRINT_PROC("\n"); PRINT_PROC("frame lists: current %p, next %p\n", hp->current_frame, hp->next_frame); PRINT_PROC("active_qe: %p\n", hp->active_qe); if (hp->active_qe) { struct m8xxhci_qe *qe = hp->active_qe; PRINT_PROC(" qe: type %d, state %d, status %d, urb %p\n", qe->qtype, qe->qstate, qe->status, qe->urb); PRINT_PROC(" len data %d, recv %d, send %d, iso_ptr %d\n", qe->data_len, qe->recv_len, qe->send_len, qe->iso_ptr); PRINT_PROC(" retries %d, busys %d\n", qe->retries, qe->busys); PRINT_PROC(" pipe %08x, devnum %d, endpoint %d\n", qe->pipe, qe->devnum, qe->endpoint); } spin_lock_irqsave(&event_lock, flags); *len += proc_frame_list("current", hp->current_frame, buffer+*len); *len += proc_frame_list("next", hp->next_frame, buffer+*len); spin_unlock_irqrestore(&event_lock, flags); return 1;}static intusb_read_log_proc(char *buffer, char **start, off_t offset, int size, int *eof, void *data){ int len = 0; off_t begin = 0; *eof = usb_proc_log_infos(buffer, &len, &begin, offset, size); if (offset >= begin + len) return 0; *start = buffer + (offset - begin); return size < begin + len - offset ? size : begin + len - offset;}static intusb_read_proc(char *buffer, char **start, off_t offset, int size, int *eof, void *data){ int len = 0; off_t begin = 0; *eof = usb_proc_infos(buffer, &len, &begin, offset, size); if (offset >= begin + len) return 0; *start = buffer + (offset - begin); return size < begin + len - offset ? size : begin + len - offset;}#endif /* CONFIG_PROC_FS *//*Universal Serial Bus Specification Revision 1.1 1588.3.5 Cyclic Redundancy ChecksCyclic redundancy checks (CRCs) are used to protect all non-PID fieldsin token and data packets. In this context, these fields areconsidered to be protected fields. The PID is not included in the CRCcheck of a packet containing a CRC. All CRCs are generated over theirrespective fields in the transmitter before bit stuffing isperformed. Similarly, CRCs are decoded in the receiver after stuffedbits have been removed. Token and data packet CRCs provide 100%coverage for all single- and double-bit errors. A failed CRC isconsidered to indicate that one or more of the protected fields iscorrupted and causes the receiver to ignore those fields, and, in mostcases, the entire packet.For CRC generation and checking, the shift registers in the generatorand checker are seeded with an all-ones pattern. For each data bitsent or received, the high order bit of the current remainder is XORedwith the data bit and then the remainder is shifted left one bit andthe low-order bit set to zero. If the result of that XOR is one, thenthe remainder is XORed with the generator polynomial.When the last bit of the checked field is sent, the CRC in thegenerator is inverted and sent to the checker MSb first. When the lastbit of the CRC is received by the checker and no errors have occurred,the remainder will be equal to the polynomial residual.A CRC error exists if the computed checksum remainder at the end of apacket reception does not match the residual.Bit stuffing requirements mustbe met for the CRC, and this includes the need to insert a zero at theend of a CRC if the preceding six bits were all ones.8.3.5.1 Token CRCsA five-bit CRC field is provided for tokens and covers the ADDR andENDP fields of IN, SETUP, and OUT tokens or the time stamp field of anSOF token. The generator polynomial is: G(X) = X 5 + X 2 + 1The binary bit pattern that represents this polynomial is 00101B. Ifall token bits are received without error, the five-bit residual atthe receiver will be 01100B.*/static unsigned int polynomial = 0x0014;static intdo_crc(int in, int bits){ unsigned char temp; unsigned int crc; crc = 0x1f; /* initial CRC */ while (bits-- > 0) { temp = in ^ crc; /* do next bit */ crc /= 2; /* update CRC */ if (temp & 0x01) /* if LSB XOR == 1 */ crc ^= polynomial; /* then XOR polynomial with CRC */ in /= 2; /* next bit */ } return crc;}static intcalc_crc5(int addr, int endpoint) { int bytes, final, crc; bytes = (endpoint << 7) | addr; crc = (~do_crc(bytes, 11)) & 0x1f; final = (crc << 11) | bytes; if (0) printk("crc 0x%x, final %08x\n", crc, final); return final;}/* ----- */static spinlock_t framelist_lock = SPIN_LOCK_UNLOCKED;/* put qe on end of list of qe's for next frame */static voidadd_to_next_frame(struct m8xxhci_qe *qe){ struct m8xxhci_private *hp = (struct m8xxhci_private *)m8xxhci_ptr; unsigned long flags; spin_lock_irqsave(&framelist_lock, flags); log_event(3, "add_to_next_frame qe", (int)qe); hp->next_frame->total_bytes += qe->data_len; hp->next_frame->bytes[qe->qtype] += qe->data_len;#ifdef DEBUG_CHECKS if (qe->qtype == Q_ISO && !list_empty(&hp->next_frame->heads[qe->qtype])) { log_event(1, "qe on next, not empty", (int)qe); log_event(1, "head qe", (int)list_entry( hp->next_frame->heads[qe->qtype].next, struct m8xxhci_qe, frame_list)); printk("qe on next, not empty\n"); m8xxhci_dump(); }#endif list_add_tail(&qe->frame_list, &hp->next_frame->heads[qe->qtype]); qe->on_frame_list = hp->next_frame; spin_unlock_irqrestore(&framelist_lock, flags);}static voidadd_to_current_frame(struct m8xxhci_qe *qe){ struct m8xxhci_private *hp = (struct m8xxhci_private *)m8xxhci_ptr; unsigned long flags; spin_lock_irqsave(&framelist_lock, flags); if (0) printk("add_to_current_frame(qe=%p)\n", qe); log_event(3, "add_to_current_frame qe", (int)qe); if (0) log_event(3, "active_qe", (int)hp->active_qe); hp->current_frame->total_bytes += qe->data_len; hp->current_frame->bytes[qe->qtype] += qe->data_len;#ifdef DEBUG_CHECKS if (qe->qtype == Q_ISO && !list_empty(&hp->current_frame->heads[qe->qtype])) { printk("qe on current, not empty\n"); m8xxhci_dump(); }#endif list_add_tail(&qe->frame_list, &hp->current_frame->heads[qe->qtype]); qe->on_frame_list = hp->current_frame; spin_unlock_irqrestore(&framelist_lock, flags);}static struct m8xxhci_qe *take_from_current_frame(int qtype){ struct m8xxhci_private *hp = (struct m8xxhci_private *)m8xxhci_ptr; unsigned long flags; struct list_head *list; struct m8xxhci_qe *qe = NULL; spin_lock_irqsave(&framelist_lock, flags); list = &hp->current_frame->heads[qtype]; if (!list_empty(list)) { /* take the top of the list */ qe = list_entry(list->next, struct m8xxhci_qe, frame_list); if (0) printk("take_from_current_frame(qtype=%d) " "top %p, top->next %p, list %p, qe %p\n", qtype, list->next, list->next->next, list, qe); log_event(3, "take_from_current_frame qe", (int)qe); list_del(&qe->frame_list); INIT_LIST_HEAD(&qe->frame_list); qe->on_frame_list = 0; hp->current_frame->total_bytes -= qe->data_len; hp->current_frame->bytes[qe->qtype] -= qe->data_len; } spin_unlock_irqrestore(&framelist_lock, flags); return qe;}static voiddump_frame_list(char *what, struct m8xxhci_frame *f){ int i; struct list_head *head, *l; struct m8xxhci_qe *qe; unsigned long flags; spin_lock_irqsave(&event_lock, flags); if (f == 0) { printk("%s: %p; <unset>\n", what, f); return; } printk("%s: %p, total_bytes %d\n", what, f, f->total_bytes); for (i = 0; i < MAX_Q_TYPES; i++) { if (f->heads[i].next == &f->heads[i]) { printk("[%d] empty\n", i); continue; } printk("[%d] bytes %d, head %p next %p prev %p\n", i, f->bytes[i], &f->heads[i], f->heads[i].next, f->heads[i].prev); head = &f->heads[i]; for (l = head->next; l != head; l = l->next) { qe = list_entry(l, struct m8xxhci_qe, qe_list); printk(" l %p, next %p, prev %p, qe %p\n", l, l->next, l->prev, qe); printk(" qe->urb %p, state %d, status %d\n", qe->urb, qe->qstate, qe->status); } } spin_unlock_irqrestore(&event_lock, flags);}static voiddump_frame_lists(void){ struct m8xxhci_private *hp = (struct m8xxhci_private *)m8xxhci_ptr; printk("frame lists: current %p, next %p\n", hp->current_frame, hp->next_frame);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -