Changeset d5abaf4 in mainline for uspace/drv/bus/usb/ohci/ohci_batch.c


Ignore:
Timestamp:
2011-10-16T15:16:22Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
dab3112
Parents:
70d72dd
Message:

ohci: Rework transfer completion routine.

Include 'not completed' fast check.
Check all assumptions using asserts.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ohci/ohci_batch.c

    r70d72dd rd5abaf4  
    163163            ohci_batch->ed->td_tail, ohci_batch->ed->next);
    164164
    165         size_t i = 0;
    166         for (; i < ohci_batch->td_count; ++i) {
     165        if (!ed_inactive(ohci_batch->ed) && ed_transfer_pending(ohci_batch->ed))
     166                return false;
     167
     168        /* Now we may be sure that either the ED is inactive because of errors
     169         * or all transfer descriptors completed successfully */
     170
     171        /* Assume all data got through */
     172        ohci_batch->usb_batch->transfered_size =
     173            ohci_batch->usb_batch->buffer_size;
     174        /* Assume we will leave the last td behind */
     175        ohci_batch->leave_td = ohci_batch->td_count;
     176
     177        /* Check all TDs */
     178        for (size_t i = 0; i < ohci_batch->td_count; ++i) {
    167179                assert(ohci_batch->tds[i] != NULL);
    168180                usb_log_debug("TD %zu: %08x:%08x:%08x:%08x.\n", i,
    169181                    ohci_batch->tds[i]->status, ohci_batch->tds[i]->cbp,
    170182                    ohci_batch->tds[i]->next, ohci_batch->tds[i]->be);
    171                 if (!td_is_finished(ohci_batch->tds[i])) {
    172                         return false;
    173                 }
     183
     184                /* If the TD got all its data through, it will report 0 bytes
     185                 * remain, the sole exception is INPUT with data rounding flag
     186                 * (short), i.e. every INPUT. Nice thing is that short packets
     187                 * will correctly report remaining data, thus making
     188                 * this computation correct (short packets need to be produced
     189                 * by the last TD)
     190                 * NOTE: This also works for CONTROL transfer as
     191                 * the first TD will return 0 remain.
     192                 * NOTE: Short packets don't break the assumption that
     193                 * we leave the very last(unused) TD behind.
     194                 */
     195                ohci_batch->usb_batch->transfered_size
     196                    -= td_remain_size(ohci_batch->tds[i]);
     197
    174198                ohci_batch->usb_batch->error = td_error(ohci_batch->tds[i]);
    175199                if (ohci_batch->usb_batch->error != EOK) {
     
    177201                            ohci_batch->usb_batch, i,
    178202                            ohci_batch->tds[i]->status);
    179                         /* Make sure TD queue is empty (one TD),
    180                          * ED should be marked as halted */
    181                         ohci_batch->ed->td_tail =
    182                             (ohci_batch->ed->td_head & ED_TDTAIL_PTR_MASK);
    183                         ++i;
     203
     204                        /* ED should be stopped because of errors */
     205                        assert((ohci_batch->ed->td_head & ED_TDHEAD_HALTED_FLAG) != 0);
     206
     207                        /* Now we have a problem: we don't know what TD
     208                         * the head pointer points to, the retiring rules
     209                         * described in specs say it should be the one after
     210                         * the failed one so set the tail pointer accordingly.
     211                         * It will be the one TD we leave behind.
     212                         */
     213                        ohci_batch->leave_td = i + 1;
     214
     215                        /* Check TD assumption */
     216                        const uint32_t pa = addr_to_phys(
     217                            ohci_batch->tds[ohci_batch->leave_td]);
     218                        assert((ohci_batch->ed->td_head & ED_TDTAIL_PTR_MASK)
     219                            == pa);
     220
     221                        ed_set_tail_td(ohci_batch->ed,
     222                            ohci_batch->tds[ohci_batch->leave_td]);
     223
     224                        /* Clear possible ED HALT */
     225                        ohci_batch->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
    184226                        break;
    185227                }
    186228        }
    187 
    188         assert(i <= ohci_batch->td_count);
    189         ohci_batch->leave_td = i;
    190 
     229        assert(ohci_batch->usb_batch->transfered_size <=
     230            ohci_batch->usb_batch->buffer_size);
     231
     232        /* Store the remaining TD */
    191233        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep);
    192234        assert(ohci_ep);
    193235        ohci_ep->td = ohci_batch->tds[ohci_batch->leave_td];
     236#if 0
    194237        assert(i > 0);
    195238        ohci_batch->usb_batch->transfered_size =
     
    199242                    -= td_remain_size(ohci_batch->tds[i]);
    200243        }
    201 
    202         /* Clear possible ED HALT */
    203         ohci_batch->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
    204         /* just make sure that we are leaving the right TD behind */
     244#endif
     245        /* Just make sure that we are leaving the right TD behind */
    205246        const uint32_t pa = addr_to_phys(ohci_ep->td);
    206247        assert(pa == (ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK));
Note: See TracChangeset for help on using the changeset viewer.