/** * @brief makes a buffer of TDs and returs the top TD * @param host struct uhci_host * @param buf_phys phys32_t * @param size size_t * @param deviceaddress u8 * @param epdesc struct usb_endpoint_descriptor * @param maxpktsz size_t * @param status u32 */ static struct uhci_td_meta * prepare_buffer_tds(struct uhci_host *host, phys32_t buf_phys, size_t size, u8 deviceaddress, struct usb_endpoint_descriptor *epdesc, size_t maxpktsz, u32 status) { struct uhci_td_meta *tdm = NULL, *next_tdm = NULL; int n_td, i; size_t pktsz; n_td = size / maxpktsz; pktsz = size % maxpktsz; /* rounding them for the final one */ if (pktsz == 0) { pktsz = maxpktsz; } else { n_td += 1; } if (size == 0) { /* for ZERO OUT */ n_td += 1; pktsz = 0; } /* create TDs in reverse (from the final to the 1st) */ buf_phys += maxpktsz * n_td; for (i = n_td; i > 0; i--) { tdm = uhci_new_td_meta(host, NULL); if (!tdm) return 0ULL; tdm->td->link = (next_tdm) ? next_tdm->td_phys : UHCI_TD_LINK_TE; tdm->next = next_tdm; tdm->td->status = tdm->status_copy = status; tdm->td->token = tdm->token_copy = uhci_td_explen(pktsz) | UHCI_TD_TOKEN_ENDPOINT(epdesc->bEndpointAddress) | UHCI_TD_TOKEN_DEVADDRESS(deviceaddress) | uhci_pid_from_ep(epdesc); buf_phys = tdm->td->buffer = buf_phys - maxpktsz; next_tdm = tdm; pktsz = maxpktsz; /* for other packets, except for the final */ } return tdm; }
/** * @brief makes a buffer of TDs and returs the top TD * @param host struct uhci_host * @param buf_phys phys32_t * @param size size_t * @param deviceaddress u8 * @param epdesc struct usb_endpoint_descriptor * @param status u32 */ static struct uhci_td_meta * prepare_buffer_tds(struct uhci_host *host, phys32_t buf_phys, size_t size, u8 deviceaddress, struct usb_endpoint_descriptor *epdesc, u32 status) { struct uhci_td_meta *tdm = NULL, *next_tdm = NULL; int n_td, i; size_t pktsize, maxlen; pktsize = epdesc->wMaxPacketSize; n_td = (size + (pktsize - 1)) / pktsize; maxlen = (size % pktsize) ? (size % pktsize) : pktsize; if (!size) { /* for ZERO OUT */ n_td += 1; maxlen = 0; } buf_phys += pktsize * n_td; for (i=n_td; i>0; i--) { tdm = uhci_new_td_meta(host, NULL); if (!tdm) return 0ULL; tdm->td->link = (next_tdm) ? next_tdm->td_phys : UHCI_TD_LINK_TE; tdm->next = next_tdm; tdm->td->status = tdm->status_copy = status; tdm->td->token = tdm->token_copy = uhci_td_explen(maxlen) | UHCI_TD_TOKEN_ENDPOINT(epdesc->bEndpointAddress) | UHCI_TD_TOKEN_DEVADDRESS(deviceaddress) | uhci_pid_from_ep(epdesc); buf_phys = tdm->td->buffer = buf_phys - pktsize; next_tdm = tdm; maxlen = pktsize; } return tdm; }