Ignore:
Timestamp:
2011-10-17T07:29:44Z (13 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
12f55220
Parents:
25696fea (diff), 1f131fb9 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge with mainline

File:
1 edited

Legend:

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

    r25696fea r22ceff3a  
    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
     175        /* Assume we will leave the last(unused) TD behind */
     176        ohci_batch->leave_td = ohci_batch->td_count;
     177
     178        /* Check all TDs */
     179        for (size_t i = 0; i < ohci_batch->td_count; ++i) {
    167180                assert(ohci_batch->tds[i] != NULL);
    168181                usb_log_debug("TD %zu: %08x:%08x:%08x:%08x.\n", i,
    169182                    ohci_batch->tds[i]->status, ohci_batch->tds[i]->cbp,
    170183                    ohci_batch->tds[i]->next, ohci_batch->tds[i]->be);
    171                 if (!td_is_finished(ohci_batch->tds[i])) {
    172                         return false;
    173                 }
     184
     185                /* If the TD got all its data through, it will report 0 bytes
     186                 * remain, the sole exception is INPUT with data rounding flag
     187                 * (short), i.e. every INPUT. Nice thing is that short packets
     188                 * will correctly report remaining data, thus making
     189                 * this computation correct (short packets need to be produced
     190                 * by the last TD)
     191                 * NOTE: This also works for CONTROL transfer as
     192                 * the first TD will return 0 remain.
     193                 * NOTE: Short packets don't break the assumption that
     194                 * we leave the very last(unused) TD behind.
     195                 */
     196                ohci_batch->usb_batch->transfered_size
     197                    -= td_remain_size(ohci_batch->tds[i]);
     198
    174199                ohci_batch->usb_batch->error = td_error(ohci_batch->tds[i]);
    175200                if (ohci_batch->usb_batch->error != EOK) {
     
    177202                            ohci_batch->usb_batch, i,
    178203                            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;
     204
     205                        /* ED should be stopped because of errors */
     206                        assert((ohci_batch->ed->td_head & ED_TDHEAD_HALTED_FLAG) != 0);
     207
     208                        /* Now we have a problem: we don't know what TD
     209                         * the head pointer points to, the retiring rules
     210                         * described in specs say it should be the one after
     211                         * the failed one so set the tail pointer accordingly.
     212                         * It will be the one TD we leave behind.
     213                         */
     214                        ohci_batch->leave_td = i + 1;
     215
     216                        /* Check TD assumption */
     217                        const uint32_t pa = addr_to_phys(
     218                            ohci_batch->tds[ohci_batch->leave_td]);
     219                        assert((ohci_batch->ed->td_head & ED_TDTAIL_PTR_MASK)
     220                            == pa);
     221
     222                        ed_set_tail_td(ohci_batch->ed,
     223                            ohci_batch->tds[ohci_batch->leave_td]);
     224
     225                        /* Clear possible ED HALT */
     226                        ohci_batch->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
    184227                        break;
    185228                }
    186229        }
    187 
    188         assert(i <= ohci_batch->td_count);
    189         ohci_batch->leave_td = i;
    190 
     230        assert(ohci_batch->usb_batch->transfered_size <=
     231            ohci_batch->usb_batch->buffer_size);
     232
     233        /* Store the remaining TD */
    191234        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep);
    192235        assert(ohci_ep);
    193236        ohci_ep->td = ohci_batch->tds[ohci_batch->leave_td];
    194         assert(i > 0);
    195         ohci_batch->usb_batch->transfered_size =
    196             ohci_batch->usb_batch->buffer_size;
    197         for (--i;i < ohci_batch->td_count; ++i) {
    198                 ohci_batch->usb_batch->transfered_size
    199                     -= td_remain_size(ohci_batch->tds[i]);
    200         }
    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 */
     237
     238        /* Make sure that we are leaving the right TD behind */
    205239        const uint32_t pa = addr_to_phys(ohci_ep->td);
    206240        assert(pa == (ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK));
     
    217251{
    218252        assert(ohci_batch);
    219         ed_set_end_td(ohci_batch->ed, ohci_batch->tds[ohci_batch->td_count]);
     253        ed_set_tail_td(ohci_batch->ed, ohci_batch->tds[ohci_batch->td_count]);
    220254}
    221255/*----------------------------------------------------------------------------*/
     
    247281        const usb_direction_t status_dir = reverse_dir[dir];
    248282
    249         /* setup stage */
    250         td_init(ohci_batch->tds[0], USB_DIRECTION_BOTH, buffer,
    251                 ohci_batch->usb_batch->setup_size, toggle);
    252         td_set_next(ohci_batch->tds[0], ohci_batch->tds[1]);
     283        /* Setup stage */
     284        td_init(
     285            ohci_batch->tds[0], ohci_batch->tds[1], USB_DIRECTION_BOTH,
     286            buffer, ohci_batch->usb_batch->setup_size, toggle);
    253287        usb_log_debug("Created CONTROL SETUP TD: %08x:%08x:%08x:%08x.\n",
    254288            ohci_batch->tds[0]->status, ohci_batch->tds[0]->cbp,
     
    256290        buffer += ohci_batch->usb_batch->setup_size;
    257291
    258         /* data stage */
     292        /* Data stage */
    259293        size_t td_current = 1;
    260294        size_t remain_size = ohci_batch->usb_batch->buffer_size;
     
    265299                toggle = 1 - toggle;
    266300
    267                 td_init(ohci_batch->tds[td_current], data_dir, buffer,
    268                     transfer_size, toggle);
    269                 td_set_next(ohci_batch->tds[td_current],
    270                     ohci_batch->tds[td_current + 1]);
     301                td_init(ohci_batch->tds[td_current],
     302                    ohci_batch->tds[td_current + 1],
     303                    data_dir, buffer, transfer_size, toggle);
    271304                usb_log_debug("Created CONTROL DATA TD: %08x:%08x:%08x:%08x.\n",
    272305                    ohci_batch->tds[td_current]->status,
     
    281314        }
    282315
    283         /* status stage */
     316        /* Status stage */
    284317        assert(td_current == ohci_batch->td_count - 1);
    285         td_init(ohci_batch->tds[td_current], status_dir, NULL, 0, 1);
    286         td_set_next(ohci_batch->tds[td_current],
    287             ohci_batch->tds[td_current + 1]);
     318        td_init(ohci_batch->tds[td_current], ohci_batch->tds[td_current + 1],
     319            status_dir, NULL, 0, 1);
    288320        usb_log_debug("Created CONTROL STATUS TD: %08x:%08x:%08x:%08x.\n",
    289321            ohci_batch->tds[td_current]->status,
     
    323355                    ? OHCI_TD_MAX_TRANSFER : remain_size;
    324356
    325                 td_init(ohci_batch->tds[td_current], dir, buffer,
    326                     transfer_size, -1);
    327                 td_set_next(ohci_batch->tds[td_current],
    328                     ohci_batch->tds[td_current + 1]);
     357                td_init(
     358                    ohci_batch->tds[td_current], ohci_batch->tds[td_current + 1],
     359                    dir, buffer, transfer_size, -1);
    329360
    330361                usb_log_debug("Created DATA TD: %08x:%08x:%08x:%08x.\n",
Note: See TracChangeset for help on using the changeset viewer.