26extern uint32_t _PFList[FL_SIZE];
28static const uint16_t sitd_OUT_Smask [] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f };
30static int ehci_iso_split_xfer(UTR_T *utr, ISO_EP_T *iso_ep);
37static int review_itd(iTD_T *itd)
40 uint32_t frnidx = itd->sched_frnidx;
41 uint32_t now_frame = (_ehci->UFINDR >> 3) & 0x3FF;
46 if (now_frame == frnidx)
48 for (i = 0; i < 8; i++)
50 if (itd->Transaction[i] & ITD_STATUS_ACTIVE)
54 else if (now_frame > frnidx)
56 if ((now_frame - frnidx) > EHCI_ISO_RCLM_RANGE)
61 if (now_frame + FL_SIZE - frnidx > EHCI_ISO_RCLM_RANGE)
70 for (i = 0; i < 8; i++)
72 if (!(itd->trans_mask & (0x1<<i)))
75 if (ITD_STATUS(itd->Transaction[i]))
77 if (itd->Transaction[i] & ITD_STATUS_ACTIVE)
82 else if (itd->Transaction[i] & ITD_STATUS_BABBLE)
87 else if (itd->Transaction[i] & ITD_STATUS_BUFF_ERR)
100 utr->iso_status[fidx] = 0;
101 utr->iso_xlen[fidx] = ITD_XFER_LEN(itd->Transaction[i]);
107 if (utr->td_cnt == 0)
109 utr->bIsTransferDone = 1;
122static int review_sitd(siTD_T *sitd)
125 uint32_t frnidx = sitd->sched_frnidx;
126 uint32_t now_frame = (_ehci->UFINDR >> 3) & 0x3FF;
128 uint32_t TotalBytesToTransfer;
130 if (now_frame == frnidx)
132 if (SITD_STATUS(sitd->StsCtrl) == SITD_STATUS_ACTIVE)
135 else if (now_frame > frnidx)
137 if ((now_frame - frnidx) > EHCI_ISO_RCLM_RANGE)
142 if (now_frame + FL_SIZE - frnidx > EHCI_ISO_RCLM_RANGE)
152 if (SITD_STATUS(sitd->StsCtrl))
154 if (sitd->StsCtrl & SITD_STATUS_ACTIVE)
158 else if (sitd->StsCtrl & SITD_BABBLE_DETECTED)
163 else if (sitd->StsCtrl & SITD_STATUS_BUFF_ERR)
176 TotalBytesToTransfer = (sitd->StsCtrl & SITD_XFER_CNT_Msk) >> SITD_XFER_CNT_Pos;
177 utr->iso_xlen[fidx] = utr->iso_xlen[fidx] - TotalBytesToTransfer;
178 utr->iso_status[fidx] = 0;
182 if (utr->td_cnt == 0)
184 utr->bIsTransferDone = 1;
195void scan_isochronous_list(
void)
197 ISO_EP_T *iso_ep = iso_ep_list;
198 iTD_T *itd, *itd_pre, *p;
199 siTD_T *sitd, *sitd_pre, *sp;
204 while (iso_ep !=
NULL)
209 itd = iso_ep->itd_list;
218 frnidx = itd->sched_frnidx;
219 if (_PFList[frnidx] == ITD_HLNK_ITD(itd))
222 _PFList[frnidx] = itd->Next_Link;
226 p = ITD_PTR(_PFList[frnidx]);
227 while ((ITD_PTR(p->Next_Link) != itd) && (p !=
NULL))
229 p = ITD_PTR(p->Next_Link);
234 USB_error(
"An iTD lost refernece to periodic frame list! 0x%x -> %d\n", (
int)itd, frnidx);
238 p->Next_Link = itd->Next_Link;
247 iso_ep->itd_list = itd->next;
251 itd_pre->next = itd->next;
267 sitd = iso_ep->sitd_list;
271 if (review_sitd(sitd))
276 frnidx = sitd->sched_frnidx;
277 if (_PFList[frnidx] == SITD_HLNK_SITD(sitd))
280 _PFList[frnidx] = sitd->Next_Link;
284 sp = SITD_PTR(_PFList[frnidx]);
285 while ((SITD_PTR(sp->Next_Link) != sitd) && (sp !=
NULL))
287 sp = SITD_PTR(sp->Next_Link);
292 USB_error(
"An siTD lost reference to periodic frame list! 0x%x -> %d\n", (
int)sitd, frnidx);
296 sp->Next_Link = sitd->Next_Link;
303 if (sitd_pre ==
NULL)
305 iso_ep->sitd_list = sitd->next;
309 sitd_pre->next = sitd->next;
312 free_ehci_siTD(sitd);
322 iso_ep = iso_ep->next;
329static void write_itd_info(UTR_T *utr, iTD_T *itd)
331 UDEV_T *udev = utr->udev;
332 EP_INFO_T *ep = utr->ep;
333 uint32_t buff_page_addr;
336 buff_page_addr = itd->buff_base & 0xFFFFF000;
338 for (i = 0; i < 7; i++)
340 itd->Bptr[i] = buff_page_addr + (0x1000 * i);
343 itd->Bptr[0] |= (udev->dev_num) | ((ep->bEndpointAddress & 0xF) << ITD_EP_NUM_Pos);
344 itd->Bptr[1] |= ep->wMaxPacketSize;
346 if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_IN)
347 itd->Bptr[1] |= ITD_DIR_IN;
349 itd->Bptr[1] |= ITD_DIR_OUT;
351 itd->Bptr[2] |= (ep->wMaxPacketSize + 1023)/1024;
354static void write_itd_micro_frame(UTR_T *utr,
int fidx, iTD_T *itd,
int mf)
358 buff_addr = (uint32_t)(utr->iso_buff[fidx]);
360 itd->Transaction[mf] = ITD_STATUS_ACTIVE |
361 ((utr->iso_xlen[fidx] & 0xFFF) << ITD_XLEN_Pos) |
362 ((buff_addr & 0xFFFFF000) - (itd->buff_base & 0xFFFFF000)) |
367static void remove_iso_ep_from_list(ISO_EP_T *iso_ep)
371 if (iso_ep_list == iso_ep)
373 iso_ep_list = iso_ep->next;
378 while (p->next !=
NULL)
380 if (p->next == iso_ep)
391 p->next = iso_ep->next;
395static __inline
void add_itd_to_iso_ep(ISO_EP_T *iso_ep, iTD_T *itd)
401 if (iso_ep->itd_list ==
NULL)
403 iso_ep->itd_list = itd;
410 p = iso_ep->itd_list;
411 while (p->next !=
NULL)
418int ehci_iso_xfer(UTR_T *utr)
420 EP_INFO_T *ep = utr->ep;
422 iTD_T *itd, *itd_next, *itd_list =
NULL;
428 if (ep->hw_pipe !=
NULL)
430 iso_ep = (ISO_EP_T *)ep->hw_pipe;
432 if (utr->bIsoNewSched)
433 iso_ep->next_frame = (((_ehci->UFINDR + (EHCI_ISO_DELAY * 8)) &
HSUSBH_UFINDR_FI_Msk) >> 3) & 0x3FF;
438 iso_ep = usbh_alloc_mem(
sizeof(*iso_ep));
442 memset(iso_ep, 0,
sizeof(*iso_ep));
444 iso_ep->next_frame = (((_ehci->UFINDR + (EHCI_ISO_DELAY * 8)) &
HSUSBH_UFINDR_FI_Msk) >> 3) & 0x3FF;
446 ep->hw_pipe = iso_ep;
452 iso_ep->next = iso_ep_list;
453 iso_ep_list = iso_ep;
457 if (utr->udev->speed == SPEED_FULL)
458 return ehci_iso_split_xfer(utr, iso_ep);
464 if (ep->bInterval <= 1)
470 else if (ep->bInterval == 2)
476 else if (ep->bInterval == 3)
482 else if (ep->bInterval == 4)
488 else if (ep->bInterval == 5)
494 else if (ep->bInterval == 6)
507 for (i = 0; i < itd_cnt; i++)
509 itd = alloc_ehci_iTD();
513 if (itd_list ==
NULL)
519 itd->next = itd_list;
524 utr->td_cnt = itd_cnt;
530 utr->iso_sf = iso_ep->next_frame;
533 for (itd = itd_list; (itd !=
NULL); )
535 if (fidx >= IF_PER_UTR)
537 USB_error(
"EHCI driver ITD bug!?\n");
543 itd->buff_base = (uint32_t)(utr->iso_buff[fidx]);
544 itd->trans_mask = trans_mask;
546 write_itd_info(utr, itd);
548 for (i = 0; i < 8; i++)
550 if (!(trans_mask & (0x1<<i)))
552 itd->Transaction[i] = 0;
556 write_itd_micro_frame(utr, fidx, itd, i);
560 if (fidx == IF_PER_UTR)
563 itd->Transaction[i] |= ITD_IOC;
568 itd_next = itd->next;
575 itd->sched_frnidx = iso_ep->next_frame;
576 add_itd_to_iso_ep(iso_ep, itd);
577 itd->Next_Link = _PFList[itd->sched_frnidx];
578 _PFList[itd->sched_frnidx] = ITD_HLNK_ITD(itd);
579 iso_ep->next_frame = (iso_ep->next_frame + interval) % FL_SIZE;
590 while (itd_list !=
NULL)
593 itd_list = itd->next;
599static __inline
void add_sitd_to_iso_ep(ISO_EP_T *iso_ep, siTD_T *sitd)
605 if (iso_ep->sitd_list ==
NULL)
607 iso_ep->sitd_list = sitd;
614 p = iso_ep->sitd_list;
615 while (p->next !=
NULL)
622static void write_sitd_info(UTR_T *utr, siTD_T *sitd)
624 UDEV_T *udev = utr->udev;
625 EP_INFO_T *ep = utr->ep;
626 uint32_t buff_page_addr;
627 int xlen = utr->iso_xlen[sitd->fidx];
630 sitd->Chrst = (udev->port_num << SITD_PORT_NUM_Pos) |
631 (udev->parent->iface->udev->dev_num << SITD_HUB_ADDR_Pos) |
632 ((ep->bEndpointAddress & 0xF) << SITD_EP_NUM_Pos) |
633 (udev->dev_num << SITD_DEV_ADDR_Pos);
635 buff_page_addr = ((uint32_t)utr->iso_buff[sitd->fidx]) & 0xFFFFF000;
636 sitd->Bptr[0] = (uint32_t)(utr->iso_buff[sitd->fidx]);
637 sitd->Bptr[1] = buff_page_addr + 0x1000;
639 scnt = (xlen + 187) / 188;
641 if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_IN)
643 sitd->Chrst |= SITD_XFER_IN;
644 sitd->Sched = (1 << (scnt + 2)) - 1;
645 sitd->Sched = (sitd->Sched << 10) | 0x1;
650 sitd->Chrst |= SITD_XFER_OUT;
651 sitd->Sched = sitd_OUT_Smask[scnt-1];
654 sitd->Bptr[1] |= (0x1 << 3);
656 sitd->Bptr[1] |= scnt;
659 if (sitd->fidx == IF_PER_UTR)
661 sitd->Sched |= SITD_IOC;
664 sitd->StsCtrl = (xlen << SITD_XFER_CNT_Pos) | SITD_STATUS_ACTIVE;
666 sitd->BackLink = SITD_LIST_END;
670static void ehci_sitd_adjust_schedule(siTD_T *sitd)
672 siTD_T *hlink = (siTD_T *)_PFList[sitd->sched_frnidx];
673 uint32_t uframe_mask = 0x00;
675 while (hlink && !HLINK_IS_TERMINATED(hlink) && HLINK_IS_SITD(hlink))
677 hlink = SITD_PTR(hlink);
680 if ((hlink->Chrst & SITD_XFER_IO_Msk) == SITD_XFER_IN)
682 uframe_mask |= (hlink->Sched & 0xFF);
683 uframe_mask |= ((hlink->Sched >> 8) & 0xFF);
687 uframe_mask |= (hlink->Sched & 0xFF);
690 hlink = SITD_PTR(hlink->Next_Link);
693 uframe_mask = uframe_mask | (uframe_mask << 8);
702 if (sitd->Sched & uframe_mask)
704 sitd->Sched = (sitd->Sched & 0xFFFF0000) | ((sitd->Sched << 1) & 0xFFFF);
715static int ehci_iso_split_xfer(UTR_T *utr, ISO_EP_T *iso_ep)
717 EP_INFO_T *ep = utr->ep;
718 siTD_T *sitd, *sitd_next, *sitd_list =
NULL;
722 if (utr->udev->parent ==
NULL)
724 USB_error(
"siso xfer - parent lost!\n");
731 for (i = 0; i < IF_PER_UTR; i++)
733 sitd = alloc_ehci_siTD();
737 if (sitd_list ==
NULL)
743 sitd->next = sitd_list;
748 utr->td_cnt = IF_PER_UTR;
754 utr->iso_sf = iso_ep->next_frame;
757 for (sitd = sitd_list; (sitd !=
NULL); fidx++)
759 if (fidx >= IF_PER_UTR)
761 USB_error(
"EHCI driver siTD bug!?\n");
768 write_sitd_info(utr, sitd);
770 sitd_next = sitd->next;
776 sitd->sched_frnidx = iso_ep->next_frame;
778 ehci_sitd_adjust_schedule(sitd);
779 add_sitd_to_iso_ep(iso_ep, sitd);
780 sitd->Next_Link = _PFList[sitd->sched_frnidx];
781 _PFList[sitd->sched_frnidx] = SITD_HLNK_SITD(sitd);
782 iso_ep->next_frame = (iso_ep->next_frame + ep->bInterval) % FL_SIZE;
793 while (sitd_list !=
NULL)
796 sitd_list = sitd->next;
797 free_ehci_siTD(sitd);
805int ehci_quit_iso_xfer(UTR_T *utr, EP_INFO_T *ep)
808 iTD_T *itd, *itd_next, *p;
823 if ((ep->bmAttributes & EP_ATTR_TT_MASK) != EP_ATTR_TT_ISO)
829 iso_ep = iso_ep_list;
830 while (iso_ep !=
NULL)
832 if (iso_ep->ep == ep)
834 iso_ep = iso_ep->next;
839 itd = iso_ep->itd_list;
843 itd_next = itd->next;
849 frnidx = itd->sched_frnidx;
857 now_frame = (_ehci->UFINDR >> 3) & 0x3FF;
858 if ((now_frame == frnidx) || (((now_frame+1)%1024) == frnidx))
863 if (_PFList[frnidx] == ITD_HLNK_ITD(itd))
866 _PFList[frnidx] = itd->Next_Link;
870 p = ITD_PTR(_PFList[frnidx]);
871 while ((ITD_PTR(p->Next_Link) != itd) && (p !=
NULL))
873 p = ITD_PTR(p->Next_Link);
878 USB_error(
"ehci_quit_iso_xfer - An iTD lost reference to periodic frame list! 0x%x on %d\n", (
int)itd, frnidx);
882 p->Next_Link = itd->Next_Link;
888 if (utr->td_cnt == 0)
890 utr->bIsTransferDone = 1;
902 remove_iso_ep_from_list(iso_ep);
903 usbh_free_mem(iso_ep,
sizeof(*iso_ep));
906 if (iso_ep_list ==
NULL)
907 _ehci->UCMDR &= ~HSUSBH_UCMDR_PSEN_Msk;
NuMicro peripheral access layer header file.
#define NULL
NULL pointer.
#define HSUSBH_UFINDR_FI_Msk
#define HSUSBH_UCMDR_PSEN_Msk
#define USBH_ERR_NOT_ACCESS0
#define USBH_ERR_TRANSFER
#define USBH_ERR_BABBLE_DETECTED
#define USBH_ERR_INVALID_PARAM
#define USBH_ERR_TRANSACTION
#define USBH_ERR_NOT_FOUND
#define USBH_ERR_DATA_BUFF
#define USBH_ERR_MEMORY_OUT
USB Host hub class driver header file.
USB Host library header file.