Revision 7bfe5777
b/hw/usb-ohci.c | ||
---|---|---|
32 | 32 |
//#define DEBUG_OHCI |
33 | 33 |
/* Dump packet contents. */ |
34 | 34 |
//#define DEBUG_PACKET |
35 |
//#define DEBUG_ISOCH |
|
35 | 36 |
/* This causes frames to occur 1000x slower */ |
36 | 37 |
//#define OHCI_TIME_WARP 1 |
37 | 38 |
|
... | ... | |
132 | 133 |
#define OHCI_ED_S (1<<13) |
133 | 134 |
#define OHCI_ED_K (1<<14) |
134 | 135 |
#define OHCI_ED_F (1<<15) |
135 |
#define OHCI_ED_MPS_SHIFT 7
|
|
136 |
#define OHCI_ED_MPS_MASK (0xf<<OHCI_ED_FA_SHIFT)
|
|
136 |
#define OHCI_ED_MPS_SHIFT 16
|
|
137 |
#define OHCI_ED_MPS_MASK (0x7ff<<OHCI_ED_MPS_SHIFT)
|
|
137 | 138 |
|
138 | 139 |
/* Flags in the head field of an Endpoint Desciptor. */ |
139 | 140 |
#define OHCI_ED_H 1 |
... | ... | |
152 | 153 |
#define OHCI_TD_CC_SHIFT 28 |
153 | 154 |
#define OHCI_TD_CC_MASK (0xf<<OHCI_TD_CC_SHIFT) |
154 | 155 |
|
156 |
/* Bitfields for the first word of an Isochronous Transfer Desciptor. */ |
|
157 |
/* CC & DI - same as in the General Transfer Desciptor */ |
|
158 |
#define OHCI_TD_SF_SHIFT 0 |
|
159 |
#define OHCI_TD_SF_MASK (0xffff<<OHCI_TD_SF_SHIFT) |
|
160 |
#define OHCI_TD_FC_SHIFT 24 |
|
161 |
#define OHCI_TD_FC_MASK (7<<OHCI_TD_FC_SHIFT) |
|
162 |
|
|
163 |
/* Isochronous Transfer Desciptor - Offset / PacketStatusWord */ |
|
164 |
#define OHCI_TD_PSW_CC_SHIFT 12 |
|
165 |
#define OHCI_TD_PSW_CC_MASK (0xf<<OHCI_TD_PSW_CC_SHIFT) |
|
166 |
#define OHCI_TD_PSW_SIZE_SHIFT 0 |
|
167 |
#define OHCI_TD_PSW_SIZE_MASK (0xfff<<OHCI_TD_PSW_SIZE_SHIFT) |
|
168 |
|
|
169 |
#define OHCI_PAGE_MASK 0xfffff000 |
|
170 |
#define OHCI_OFFSET_MASK 0xfff |
|
171 |
|
|
155 | 172 |
#define OHCI_DPTR_MASK 0xfffffff0 |
156 | 173 |
|
157 | 174 |
#define OHCI_BM(val, field) \ |
... | ... | |
178 | 195 |
uint32_t be; |
179 | 196 |
}; |
180 | 197 |
|
198 |
/* Isochronous transfer descriptor */ |
|
199 |
struct ohci_iso_td { |
|
200 |
uint32_t flags; |
|
201 |
uint32_t bp; |
|
202 |
uint32_t next; |
|
203 |
uint32_t be; |
|
204 |
uint16_t offset[8]; |
|
205 |
}; |
|
206 |
|
|
181 | 207 |
#define USB_HZ 12000000 |
182 | 208 |
|
183 | 209 |
/* OHCI Local stuff */ |
... | ... | |
421 | 447 |
return 1; |
422 | 448 |
} |
423 | 449 |
|
450 |
/* Get an array of words from main memory */ |
|
451 |
static inline int get_words(uint32_t addr, uint16_t *buf, int num) |
|
452 |
{ |
|
453 |
int i; |
|
454 |
|
|
455 |
for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { |
|
456 |
cpu_physical_memory_rw(addr, (uint8_t *)buf, sizeof(*buf), 0); |
|
457 |
*buf = le16_to_cpu(*buf); |
|
458 |
} |
|
459 |
|
|
460 |
return 1; |
|
461 |
} |
|
462 |
|
|
463 |
/* Put an array of words in to main memory */ |
|
464 |
static inline int put_words(uint32_t addr, uint16_t *buf, int num) |
|
465 |
{ |
|
466 |
int i; |
|
467 |
|
|
468 |
for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { |
|
469 |
uint16_t tmp = cpu_to_le16(*buf); |
|
470 |
cpu_physical_memory_rw(addr, (uint8_t *)&tmp, sizeof(tmp), 1); |
|
471 |
} |
|
472 |
|
|
473 |
return 1; |
|
474 |
} |
|
475 |
|
|
424 | 476 |
static inline int ohci_read_ed(uint32_t addr, struct ohci_ed *ed) |
425 | 477 |
{ |
426 | 478 |
return get_dwords(addr, (uint32_t *)ed, sizeof(*ed) >> 2); |
... | ... | |
431 | 483 |
return get_dwords(addr, (uint32_t *)td, sizeof(*td) >> 2); |
432 | 484 |
} |
433 | 485 |
|
486 |
static inline int ohci_read_iso_td(uint32_t addr, struct ohci_iso_td *td) |
|
487 |
{ |
|
488 |
return (get_dwords(addr, (uint32_t *)td, 4) && |
|
489 |
get_words(addr + 16, td->offset, 8)); |
|
490 |
} |
|
491 |
|
|
434 | 492 |
static inline int ohci_put_ed(uint32_t addr, struct ohci_ed *ed) |
435 | 493 |
{ |
436 | 494 |
return put_dwords(addr, (uint32_t *)ed, sizeof(*ed) >> 2); |
... | ... | |
441 | 499 |
return put_dwords(addr, (uint32_t *)td, sizeof(*td) >> 2); |
442 | 500 |
} |
443 | 501 |
|
502 |
static inline int ohci_put_iso_td(uint32_t addr, struct ohci_iso_td *td) |
|
503 |
{ |
|
504 |
return (put_dwords(addr, (uint32_t *)td, 4) && |
|
505 |
put_words(addr + 16, td->offset, 8)); |
|
506 |
} |
|
507 |
|
|
444 | 508 |
/* Read/Write the contents of a TD from/to main memory. */ |
445 | 509 |
static void ohci_copy_td(struct ohci_td *td, uint8_t *buf, int len, int write) |
446 | 510 |
{ |
... | ... | |
459 | 523 |
cpu_physical_memory_rw(ptr, buf, len - n, write); |
460 | 524 |
} |
461 | 525 |
|
462 |
static void ohci_process_lists(OHCIState *ohci); |
|
526 |
/* Read/Write the contents of an ISO TD from/to main memory. */ |
|
527 |
static void ohci_copy_iso_td(uint32_t start_addr, uint32_t end_addr, |
|
528 |
uint8_t *buf, int len, int write) |
|
529 |
{ |
|
530 |
uint32_t ptr; |
|
531 |
uint32_t n; |
|
463 | 532 |
|
464 |
static void ohci_async_complete_packet(USBPacket * packet, void *opaque) |
|
533 |
ptr = start_addr; |
|
534 |
n = 0x1000 - (ptr & 0xfff); |
|
535 |
if (n > len) |
|
536 |
n = len; |
|
537 |
cpu_physical_memory_rw(ptr, buf, n, write); |
|
538 |
if (n == len) |
|
539 |
return; |
|
540 |
ptr = end_addr & ~0xfffu; |
|
541 |
buf += n; |
|
542 |
cpu_physical_memory_rw(ptr, buf, len - n, write); |
|
543 |
} |
|
544 |
|
|
545 |
static void ohci_process_lists(OHCIState *ohci, int completion); |
|
546 |
|
|
547 |
static void ohci_async_complete_packet(USBPacket *packet, void *opaque) |
|
465 | 548 |
{ |
466 | 549 |
OHCIState *ohci = opaque; |
467 | 550 |
#ifdef DEBUG_PACKET |
468 | 551 |
dprintf("Async packet complete\n"); |
469 | 552 |
#endif |
470 | 553 |
ohci->async_complete = 1; |
471 |
ohci_process_lists(ohci); |
|
554 |
ohci_process_lists(ohci, 1); |
|
555 |
} |
|
556 |
|
|
557 |
#define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b))) |
|
558 |
|
|
559 |
static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, |
|
560 |
int completion) |
|
561 |
{ |
|
562 |
int dir; |
|
563 |
size_t len = 0; |
|
564 |
char *str = NULL; |
|
565 |
int pid; |
|
566 |
int ret; |
|
567 |
int i; |
|
568 |
USBDevice *dev; |
|
569 |
struct ohci_iso_td iso_td; |
|
570 |
uint32_t addr; |
|
571 |
uint16_t starting_frame; |
|
572 |
int16_t relative_frame_number; |
|
573 |
int frame_count; |
|
574 |
uint32_t start_offset, next_offset, end_offset = 0; |
|
575 |
uint32_t start_addr, end_addr; |
|
576 |
|
|
577 |
addr = ed->head & OHCI_DPTR_MASK; |
|
578 |
|
|
579 |
if (!ohci_read_iso_td(addr, &iso_td)) { |
|
580 |
printf("usb-ohci: ISO_TD read error at %x\n", addr); |
|
581 |
return 0; |
|
582 |
} |
|
583 |
|
|
584 |
starting_frame = OHCI_BM(iso_td.flags, TD_SF); |
|
585 |
frame_count = OHCI_BM(iso_td.flags, TD_FC); |
|
586 |
relative_frame_number = USUB(ohci->frame_number, starting_frame); |
|
587 |
|
|
588 |
#ifdef DEBUG_ISOCH |
|
589 |
printf("--- ISO_TD ED head 0x%.8x tailp 0x%.8x\n" |
|
590 |
"0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" |
|
591 |
"0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" |
|
592 |
"0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" |
|
593 |
"frame_number 0x%.8x starting_frame 0x%.8x\n" |
|
594 |
"frame_count 0x%.8x relative %d\n" |
|
595 |
"di 0x%.8x cc 0x%.8x\n", |
|
596 |
ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK, |
|
597 |
iso_td.flags, iso_td.bp, iso_td.next, iso_td.be, |
|
598 |
iso_td.offset[0], iso_td.offset[1], iso_td.offset[2], iso_td.offset[3], |
|
599 |
iso_td.offset[4], iso_td.offset[5], iso_td.offset[6], iso_td.offset[7], |
|
600 |
ohci->frame_number, starting_frame, |
|
601 |
frame_count, relative_frame_number, |
|
602 |
OHCI_BM(iso_td.flags, TD_DI), OHCI_BM(iso_td.flags, TD_CC)); |
|
603 |
#endif |
|
604 |
|
|
605 |
if (relative_frame_number < 0) { |
|
606 |
dprintf("usb-ohci: ISO_TD R=%d < 0\n", relative_frame_number); |
|
607 |
return 1; |
|
608 |
} else if (relative_frame_number > frame_count) { |
|
609 |
/* ISO TD expired - retire the TD to the Done Queue and continue with |
|
610 |
the next ISO TD of the same ED */ |
|
611 |
dprintf("usb-ohci: ISO_TD R=%d > FC=%d\n", relative_frame_number, |
|
612 |
frame_count); |
|
613 |
OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN); |
|
614 |
ed->head &= ~OHCI_DPTR_MASK; |
|
615 |
ed->head |= (iso_td.next & OHCI_DPTR_MASK); |
|
616 |
iso_td.next = ohci->done; |
|
617 |
ohci->done = addr; |
|
618 |
i = OHCI_BM(iso_td.flags, TD_DI); |
|
619 |
if (i < ohci->done_count) |
|
620 |
ohci->done_count = i; |
|
621 |
ohci_put_iso_td(addr, &iso_td); |
|
622 |
return 0; |
|
623 |
} |
|
624 |
|
|
625 |
dir = OHCI_BM(ed->flags, ED_D); |
|
626 |
switch (dir) { |
|
627 |
case OHCI_TD_DIR_IN: |
|
628 |
str = "in"; |
|
629 |
pid = USB_TOKEN_IN; |
|
630 |
break; |
|
631 |
case OHCI_TD_DIR_OUT: |
|
632 |
str = "out"; |
|
633 |
pid = USB_TOKEN_OUT; |
|
634 |
break; |
|
635 |
case OHCI_TD_DIR_SETUP: |
|
636 |
str = "setup"; |
|
637 |
pid = USB_TOKEN_SETUP; |
|
638 |
break; |
|
639 |
default: |
|
640 |
printf("usb-ohci: Bad direction %d\n", dir); |
|
641 |
return 1; |
|
642 |
} |
|
643 |
|
|
644 |
if (!iso_td.bp || !iso_td.be) { |
|
645 |
printf("usb-ohci: ISO_TD bp 0x%.8x be 0x%.8x\n", iso_td.bp, iso_td.be); |
|
646 |
return 1; |
|
647 |
} |
|
648 |
|
|
649 |
start_offset = iso_td.offset[relative_frame_number]; |
|
650 |
next_offset = iso_td.offset[relative_frame_number + 1]; |
|
651 |
|
|
652 |
if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) || |
|
653 |
((relative_frame_number < frame_count) && |
|
654 |
!(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) { |
|
655 |
printf("usb-ohci: ISO_TD cc != not accessed 0x%.8x 0x%.8x\n", |
|
656 |
start_offset, next_offset); |
|
657 |
return 1; |
|
658 |
} |
|
659 |
|
|
660 |
if ((relative_frame_number < frame_count) && (start_offset > next_offset)) { |
|
661 |
printf("usb-ohci: ISO_TD start_offset=0x%.8x > next_offset=0x%.8x\n", |
|
662 |
start_offset, next_offset); |
|
663 |
return 1; |
|
664 |
} |
|
665 |
|
|
666 |
if ((start_offset & 0x1000) == 0) { |
|
667 |
start_addr = (iso_td.bp & OHCI_PAGE_MASK) | |
|
668 |
(start_offset & OHCI_OFFSET_MASK); |
|
669 |
} else { |
|
670 |
start_addr = (iso_td.be & OHCI_PAGE_MASK) | |
|
671 |
(start_offset & OHCI_OFFSET_MASK); |
|
672 |
} |
|
673 |
|
|
674 |
if (relative_frame_number < frame_count) { |
|
675 |
end_offset = next_offset - 1; |
|
676 |
if ((end_offset & 0x1000) == 0) { |
|
677 |
end_addr = (iso_td.bp & OHCI_PAGE_MASK) | |
|
678 |
(end_offset & OHCI_OFFSET_MASK); |
|
679 |
} else { |
|
680 |
end_addr = (iso_td.be & OHCI_PAGE_MASK) | |
|
681 |
(end_offset & OHCI_OFFSET_MASK); |
|
682 |
} |
|
683 |
} else { |
|
684 |
/* Last packet in the ISO TD */ |
|
685 |
end_addr = iso_td.be; |
|
686 |
} |
|
687 |
|
|
688 |
if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) { |
|
689 |
len = (end_addr & OHCI_OFFSET_MASK) + 0x1001 |
|
690 |
- (start_addr & OHCI_OFFSET_MASK); |
|
691 |
} else { |
|
692 |
len = end_addr - start_addr + 1; |
|
693 |
} |
|
694 |
|
|
695 |
if (len && dir != OHCI_TD_DIR_IN) { |
|
696 |
ohci_copy_iso_td(start_addr, end_addr, ohci->usb_buf, len, 0); |
|
697 |
} |
|
698 |
|
|
699 |
if (completion) { |
|
700 |
ret = ohci->usb_packet.len; |
|
701 |
} else { |
|
702 |
ret = USB_RET_NODEV; |
|
703 |
for (i = 0; i < ohci->num_ports; i++) { |
|
704 |
dev = ohci->rhport[i].port.dev; |
|
705 |
if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) |
|
706 |
continue; |
|
707 |
ohci->usb_packet.pid = pid; |
|
708 |
ohci->usb_packet.devaddr = OHCI_BM(ed->flags, ED_FA); |
|
709 |
ohci->usb_packet.devep = OHCI_BM(ed->flags, ED_EN); |
|
710 |
ohci->usb_packet.data = ohci->usb_buf; |
|
711 |
ohci->usb_packet.len = len; |
|
712 |
ohci->usb_packet.complete_cb = ohci_async_complete_packet; |
|
713 |
ohci->usb_packet.complete_opaque = ohci; |
|
714 |
ret = dev->handle_packet(dev, &ohci->usb_packet); |
|
715 |
if (ret != USB_RET_NODEV) |
|
716 |
break; |
|
717 |
} |
|
718 |
|
|
719 |
if (ret == USB_RET_ASYNC) { |
|
720 |
return 1; |
|
721 |
} |
|
722 |
} |
|
723 |
|
|
724 |
#ifdef DEBUG_ISOCH |
|
725 |
printf("so 0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d\n", |
|
726 |
start_offset, end_offset, start_addr, end_addr, str, len, ret); |
|
727 |
#endif |
|
728 |
|
|
729 |
/* Writeback */ |
|
730 |
if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) { |
|
731 |
/* IN transfer succeeded */ |
|
732 |
ohci_copy_iso_td(start_addr, end_addr, ohci->usb_buf, ret, 1); |
|
733 |
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, |
|
734 |
OHCI_CC_NOERROR); |
|
735 |
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret); |
|
736 |
} else if (dir == OHCI_TD_DIR_OUT && ret == len) { |
|
737 |
/* OUT transfer succeeded */ |
|
738 |
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, |
|
739 |
OHCI_CC_NOERROR); |
|
740 |
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0); |
|
741 |
} else { |
|
742 |
if (ret > len) { |
|
743 |
printf("usb-ohci: DataOverrun %d > %zu\n", ret, len); |
|
744 |
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, |
|
745 |
OHCI_CC_DATAOVERRUN); |
|
746 |
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, |
|
747 |
len); |
|
748 |
} else if (ret >= 0) { |
|
749 |
printf("usb-ohci: DataUnderrun %d\n", ret); |
|
750 |
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, |
|
751 |
OHCI_CC_DATAUNDERRUN); |
|
752 |
} else { |
|
753 |
switch (ret) { |
|
754 |
case USB_RET_NODEV: |
|
755 |
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, |
|
756 |
OHCI_CC_DEVICENOTRESPONDING); |
|
757 |
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, |
|
758 |
0); |
|
759 |
break; |
|
760 |
case USB_RET_NAK: |
|
761 |
case USB_RET_STALL: |
|
762 |
printf("usb-ohci: got NAK/STALL %d\n", ret); |
|
763 |
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, |
|
764 |
OHCI_CC_STALL); |
|
765 |
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, |
|
766 |
0); |
|
767 |
break; |
|
768 |
default: |
|
769 |
printf("usb-ohci: Bad device response %d\n", ret); |
|
770 |
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, |
|
771 |
OHCI_CC_UNDEXPETEDPID); |
|
772 |
break; |
|
773 |
} |
|
774 |
} |
|
775 |
} |
|
776 |
|
|
777 |
if (relative_frame_number == frame_count) { |
|
778 |
/* Last data packet of ISO TD - retire the TD to the Done Queue */ |
|
779 |
OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR); |
|
780 |
ed->head &= ~OHCI_DPTR_MASK; |
|
781 |
ed->head |= (iso_td.next & OHCI_DPTR_MASK); |
|
782 |
iso_td.next = ohci->done; |
|
783 |
ohci->done = addr; |
|
784 |
i = OHCI_BM(iso_td.flags, TD_DI); |
|
785 |
if (i < ohci->done_count) |
|
786 |
ohci->done_count = i; |
|
787 |
} |
|
788 |
ohci_put_iso_td(addr, &iso_td); |
|
789 |
return 1; |
|
472 | 790 |
} |
473 | 791 |
|
474 | 792 |
/* Service a transport descriptor. |
... | ... | |
671 | 989 |
} |
672 | 990 |
|
673 | 991 |
/* Service an endpoint list. Returns nonzero if active TD were found. */ |
674 |
static int ohci_service_ed_list(OHCIState *ohci, uint32_t head) |
|
992 |
static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
|
|
675 | 993 |
{ |
676 | 994 |
struct ohci_ed ed; |
677 | 995 |
uint32_t next_ed; |
... | ... | |
702 | 1020 |
continue; |
703 | 1021 |
} |
704 | 1022 |
|
705 |
/* Skip isochronous endpoints. */ |
|
706 |
if (ed.flags & OHCI_ED_F) |
|
707 |
continue; |
|
708 |
|
|
709 | 1023 |
while ((ed.head & OHCI_DPTR_MASK) != ed.tail) { |
710 | 1024 |
#ifdef DEBUG_PACKET |
711 | 1025 |
dprintf("ED @ 0x%.8x fa=%u en=%u d=%u s=%u k=%u f=%u mps=%u " |
... | ... | |
719 | 1033 |
#endif |
720 | 1034 |
active = 1; |
721 | 1035 |
|
722 |
if (ohci_service_td(ohci, &ed)) |
|
723 |
break; |
|
1036 |
if ((ed.flags & OHCI_ED_F) == 0) { |
|
1037 |
if (ohci_service_td(ohci, &ed)) |
|
1038 |
break; |
|
1039 |
} else { |
|
1040 |
/* Handle isochronous endpoints */ |
|
1041 |
if (ohci_service_iso_td(ohci, &ed, completion)) |
|
1042 |
break; |
|
1043 |
} |
|
724 | 1044 |
} |
725 | 1045 |
|
726 | 1046 |
ohci_put_ed(cur, &ed); |
... | ... | |
738 | 1058 |
} |
739 | 1059 |
|
740 | 1060 |
/* Process Control and Bulk lists. */ |
741 |
static void ohci_process_lists(OHCIState *ohci) |
|
1061 |
static void ohci_process_lists(OHCIState *ohci, int completion)
|
|
742 | 1062 |
{ |
743 | 1063 |
if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) { |
744 | 1064 |
if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) |
745 | 1065 |
dprintf("usb-ohci: head %x, cur %x\n", ohci->ctrl_head, ohci->ctrl_cur); |
746 |
if (!ohci_service_ed_list(ohci, ohci->ctrl_head)) { |
|
1066 |
if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) {
|
|
747 | 1067 |
ohci->ctrl_cur = 0; |
748 | 1068 |
ohci->status &= ~OHCI_STATUS_CLF; |
749 | 1069 |
} |
750 | 1070 |
} |
751 | 1071 |
|
752 | 1072 |
if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) { |
753 |
if (!ohci_service_ed_list(ohci, ohci->bulk_head)) { |
|
1073 |
if (!ohci_service_ed_list(ohci, ohci->bulk_head, completion)) {
|
|
754 | 1074 |
ohci->bulk_cur = 0; |
755 | 1075 |
ohci->status &= ~OHCI_STATUS_BLF; |
756 | 1076 |
} |
... | ... | |
770 | 1090 |
int n; |
771 | 1091 |
|
772 | 1092 |
n = ohci->frame_number & 0x1f; |
773 |
ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n])); |
|
1093 |
ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]), 0);
|
|
774 | 1094 |
} |
775 | 1095 |
|
776 | 1096 |
/* Cancel all pending packets if either of the lists has been disabled. */ |
... | ... | |
780 | 1100 |
ohci->async_td = 0; |
781 | 1101 |
} |
782 | 1102 |
ohci->old_ctl = ohci->ctl; |
783 |
ohci_process_lists(ohci); |
|
1103 |
ohci_process_lists(ohci, 0);
|
|
784 | 1104 |
|
785 | 1105 |
/* Frame boundary, so do EOF stuf here */ |
786 | 1106 |
ohci->frt = ohci->fit; |
... | ... | |
1206 | 1526 |
ohci_set_frame_interval(ohci, val); |
1207 | 1527 |
break; |
1208 | 1528 |
|
1529 |
case 15: /* HcFmNumber */ |
|
1530 |
break; |
|
1531 |
|
|
1209 | 1532 |
case 16: /* HcPeriodicStart */ |
1210 | 1533 |
ohci->pstart = val & 0xffff; |
1211 | 1534 |
break; |
Also available in: Unified diff