Changeset 110d795 in mainline


Ignore:
Timestamp:
2017-07-22T23:07:40Z (7 years ago)
Author:
Jaroslav Jindrak <dzejrou@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
aee352c
Parents:
9af3281
Message:

Overhauled command system, not a special structure is passed that can be kept and polled for completion.

Location:
uspace/drv/bus/usb/xhci
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/xhci/commands.c

    r9af3281 r110d795  
    4444#include "hw_struct/trb.h"
    4545
     46int xhci_init_commands(xhci_hc_t *hc)
     47{
     48        assert(hc);
     49
     50        list_initialize(&hc->commands);
     51        return EOK;
     52}
     53
     54int xhci_wait_for_command(xhci_hc_t *hc, xhci_cmd_t *cmd, uint32_t timeout)
     55{
     56        uint32_t time = 0;
     57        while (!cmd->completed) {
     58                async_usleep(1000);
     59                time += 1000;
     60
     61                if (time > timeout)
     62                        return ETIMEOUT;
     63        }
     64
     65        return EOK;
     66}
     67
     68xhci_cmd_t *xhci_alloc_command(void)
     69{
     70        xhci_cmd_t *cmd = malloc32(sizeof(xhci_cmd_t));
     71        memset(cmd, 0, sizeof(xhci_cmd_t));
     72
     73        link_initialize(&cmd->link);
     74
     75        /**
     76         * Internal functions will set this to false, other are implicit
     77         * owners unless they overwrite this field.
     78         * TODO: Is this wise?
     79         */
     80        cmd->has_owner = true;
     81
     82        return cmd;
     83}
     84
     85void xhci_free_command(xhci_cmd_t *cmd)
     86{
     87        // TODO: If we decide to copy trb, free it here.
     88        if (cmd->ictx)
     89                free32(cmd->ictx);
     90
     91        free32(cmd);
     92}
     93
     94static inline xhci_cmd_t *get_next_command(xhci_hc_t *hc)
     95{
     96        link_t *cmd_link = list_first(&hc->commands);
     97
     98        if (cmd_link != NULL) {
     99                list_remove(cmd_link);
     100               
     101                return list_get_instance(cmd_link, xhci_cmd_t, link);
     102        }
     103
     104        return NULL;
     105}
     106
    46107static inline int ring_doorbell(xhci_hc_t *hc, unsigned doorbell, unsigned target)
    47108{
     
    65126
    66127        return EOK;
     128}
     129
     130static inline xhci_cmd_t *add_cmd(xhci_hc_t *hc, xhci_cmd_t *cmd)
     131{
     132        if (cmd == NULL) {
     133                cmd = xhci_alloc_command();
     134                if (cmd == NULL)
     135                        return cmd;
     136
     137                cmd->has_owner = false;
     138        }
     139
     140        list_append(&cmd->link, &hc->commands);
     141        cmd->trb = hc->command_ring.enqueue_trb;
     142
     143        return cmd;
    67144}
    68145
     
    118195}
    119196
    120 int xhci_send_no_op_command(xhci_hc_t *hc)
     197int xhci_send_no_op_command(xhci_hc_t *hc, xhci_cmd_t *cmd)
    121198{
    122199        assert(hc);
     
    127204        trb.control = host2xhci(32, XHCI_TRB_TYPE_NO_OP_CMD << 10);
    128205
    129         return enqueue_trb(hc, &trb, 0, 0);
    130 }
    131 
    132 int xhci_send_enable_slot_command(xhci_hc_t *hc)
     206        cmd = add_cmd(hc, cmd);
     207
     208        return enqueue_trb(hc, &trb, 0, 0);
     209}
     210
     211int xhci_send_enable_slot_command(xhci_hc_t *hc, xhci_cmd_t *cmd)
    133212{
    134213        assert(hc);
     
    141220        trb.control |= host2xhci(32, hc->command_ring.pcs);
    142221
    143         return enqueue_trb(hc, &trb, 0, 0);
    144 }
    145 
    146 int xhci_send_disable_slot_command(xhci_hc_t *hc, uint32_t slot_id)
    147 {
    148         assert(hc);
     222        cmd = add_cmd(hc, cmd);
     223
     224        return enqueue_trb(hc, &trb, 0, 0);
     225}
     226
     227int xhci_send_disable_slot_command(xhci_hc_t *hc, xhci_cmd_t *cmd)
     228{
     229        assert(hc);
     230        assert(cmd);
    149231
    150232        xhci_trb_t trb;
     
    153235        trb.control = host2xhci(32, XHCI_TRB_TYPE_DISABLE_SLOT_CMD << 10);
    154236        trb.control |= host2xhci(32, hc->command_ring.pcs);
    155         trb.control |= host2xhci(32, slot_id << 24);
    156 
    157         return enqueue_trb(hc, &trb, 0, 0);
    158 }
    159 
    160 int xhci_send_address_device_command(xhci_hc_t *hc, uint32_t slot_id,
    161                                      xhci_input_ctx_t *ictx)
    162 {
    163         assert(hc);
    164         assert(ictx);
     237        trb.control |= host2xhci(32, cmd->slot_id << 24);
     238
     239        add_cmd(hc, cmd);
     240
     241        return enqueue_trb(hc, &trb, 0, 0);
     242}
     243
     244int xhci_send_address_device_command(xhci_hc_t *hc, xhci_cmd_t *cmd)
     245{
     246        assert(hc);
     247        assert(cmd);
     248        assert(cmd->ictx);
    165249
    166250        /**
     
    173257        memset(&trb, 0, sizeof(trb));
    174258
    175         uint64_t phys_addr = (uint64_t) addr_to_phys(ictx);
     259        uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->ictx);
    176260        trb.parameter = host2xhci(32, phys_addr & (~0xF));
    177261
     
    185269        trb.control = host2xhci(32, XHCI_TRB_TYPE_ADDRESS_DEVICE_CMD << 10);
    186270        trb.control |= host2xhci(32, hc->command_ring.pcs);
    187         trb.control |= host2xhci(32, slot_id << 24);
    188 
    189         return enqueue_trb(hc, &trb, 0, 0);
    190 }
    191 
    192 int xhci_send_configure_endpoint_command(xhci_hc_t *hc, uint32_t slot_id,
    193                                          xhci_input_ctx_t *ictx)
    194 {
    195         assert(hc);
    196         assert(ictx);
    197 
    198         xhci_trb_t trb;
    199         memset(&trb, 0, sizeof(trb));
    200 
    201         uint64_t phys_addr = (uint64_t) addr_to_phys(ictx);
     271        trb.control |= host2xhci(32, cmd->slot_id << 24);
     272
     273        cmd = add_cmd(hc, cmd);
     274
     275        return enqueue_trb(hc, &trb, 0, 0);
     276}
     277
     278int xhci_send_configure_endpoint_command(xhci_hc_t *hc, xhci_cmd_t *cmd)
     279{
     280        assert(hc);
     281        assert(cmd);
     282        assert(cmd->ictx);
     283
     284        xhci_trb_t trb;
     285        memset(&trb, 0, sizeof(trb));
     286
     287        uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->ictx);
    202288        trb.parameter = host2xhci(32, phys_addr & (~0xF));
    203289
    204290        trb.control = host2xhci(32, XHCI_TRB_TYPE_CONFIGURE_ENDPOINT_CMD << 10);
    205291        trb.control |= host2xhci(32, hc->command_ring.pcs);
    206         trb.control |= host2xhci(32, slot_id << 24);
    207 
    208         return enqueue_trb(hc, &trb, 0, 0);
    209 }
    210 
    211 int xhci_send_evaluate_context_command(xhci_hc_t *hc, uint32_t slot_id,
    212                                        xhci_input_ctx_t *ictx)
    213 {
    214         assert(hc);
    215         assert(ictx);
     292        trb.control |= host2xhci(32, cmd->slot_id << 24);
     293
     294        cmd = add_cmd(hc, cmd);
     295
     296        return enqueue_trb(hc, &trb, 0, 0);
     297}
     298
     299int xhci_send_evaluate_context_command(xhci_hc_t *hc, xhci_cmd_t *cmd)
     300{
     301        assert(hc);
     302        assert(cmd);
     303        assert(cmd->ictx);
    216304
    217305        /**
     
    224312        memset(&trb, 0, sizeof(trb));
    225313
    226         uint64_t phys_addr = (uint64_t) addr_to_phys(ictx);
     314        uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->ictx);
    227315        trb.parameter = host2xhci(32, phys_addr & (~0xF));
    228316
    229317        trb.control = host2xhci(32, XHCI_TRB_TYPE_EVALUATE_CONTEXT_CMD << 10);
    230318        trb.control |= host2xhci(32, hc->command_ring.pcs);
    231         trb.control |= host2xhci(32, slot_id << 24);
    232 
    233         return enqueue_trb(hc, &trb, 0, 0);
    234 }
    235 
    236 int xhci_send_reset_endpoint_command(xhci_hc_t *hc, uint32_t slot_id, uint32_t ep_id, uint8_t tcs)
    237 {
    238         assert(hc);
     319        trb.control |= host2xhci(32, cmd->slot_id << 24);
     320
     321        cmd = add_cmd(hc, cmd);
     322
     323        return enqueue_trb(hc, &trb, 0, 0);
     324}
     325
     326int xhci_send_reset_endpoint_command(xhci_hc_t *hc, xhci_cmd_t *cmd, uint32_t ep_id, uint8_t tcs)
     327{
     328        assert(hc);
     329        assert(cmd);
    239330
    240331        /**
     
    249340        trb.control |= host2xhci(32, (tcs & 0x1) << 9);
    250341        trb.control |= host2xhci(32, (ep_id & 0x5) << 16);
    251         trb.control |= host2xhci(32, slot_id << 24);
    252 
    253         return enqueue_trb(hc, &trb, 0, 0);
    254 }
    255 
    256 int xhci_send_stop_endpoint_command(xhci_hc_t *hc, uint32_t slot_id, uint32_t ep_id, uint8_t susp)
    257 {
    258         assert(hc);
     342        trb.control |= host2xhci(32, cmd->slot_id << 24);
     343
     344        return enqueue_trb(hc, &trb, 0, 0);
     345}
     346
     347int xhci_send_stop_endpoint_command(xhci_hc_t *hc, xhci_cmd_t *cmd, uint32_t ep_id, uint8_t susp)
     348{
     349        assert(hc);
     350        assert(cmd);
    259351
    260352        xhci_trb_t trb;
     
    265357        trb.control |= host2xhci(32, (ep_id & 0x5) << 16);
    266358        trb.control |= host2xhci(32, (susp & 0x1) << 23);
    267         trb.control |= host2xhci(32, slot_id << 24);
    268 
    269         return enqueue_trb(hc, &trb, 0, 0);
    270 }
    271 
    272 int xhci_send_reset_device_command(xhci_hc_t *hc, uint32_t slot_id)
    273 {
    274         assert(hc);
     359        trb.control |= host2xhci(32, cmd->slot_id << 24);
     360
     361        cmd = add_cmd(hc, cmd);
     362
     363        return enqueue_trb(hc, &trb, 0, 0);
     364}
     365
     366int xhci_send_reset_device_command(xhci_hc_t *hc, xhci_cmd_t *cmd)
     367{
     368        assert(hc);
     369        assert(cmd);
    275370
    276371        xhci_trb_t trb;
     
    279374        trb.control = host2xhci(32, XHCI_TRB_TYPE_RESET_DEVICE_CMD << 10);
    280375        trb.control |= host2xhci(32, hc->command_ring.pcs);
    281         trb.control |= host2xhci(32, slot_id << 24);
     376        trb.control |= host2xhci(32, cmd->slot_id << 24);
    282377
    283378        return enqueue_trb(hc, &trb, 0, 0);
     
    286381int xhci_handle_command_completion(xhci_hc_t *hc, xhci_trb_t *trb)
    287382{
     383        // TODO: Update dequeue ptrs.
     384        // TODO: Possibly clone command trb, as it may get overwritten before
     385        //       it is processed (if somebody polls the command completion).
    288386        assert(hc);
    289387        assert(trb);
    290388
    291389        usb_log_debug("HC(%p) Command completed.", hc);
    292         xhci_dump_trb(trb);
    293390
    294391        int code;
    295392        uint32_t slot_id;
    296         xhci_trb_t *command;
     393        xhci_cmd_t *command;
     394        xhci_trb_t *command_trb;
    297395
    298396        code = XHCI_DWORD_EXTRACT(trb->status, 31, 24);
    299         command = (xhci_trb_t *) XHCI_QWORD_EXTRACT(trb->parameter, 63, 4);
    300397        slot_id = XHCI_DWORD_EXTRACT(trb->control, 31, 24);
    301398        (void) slot_id;
    302399
    303         if (TRB_TYPE(*command) != XHCI_TRB_TYPE_NO_OP_CMD) {
     400        command = get_next_command(hc);
     401        assert(command);
     402
     403        command_trb = command->trb;
     404
     405        code = XHCI_DWORD_EXTRACT(trb->status, 31, 24);
     406        command->status = code;
     407
     408        slot_id = XHCI_DWORD_EXTRACT(trb->control, 31, 24);
     409        command->slot_id = slot_id;
     410
     411        usb_log_debug2("Completed command trb:");
     412        xhci_dump_trb(command_trb);
     413        if (TRB_TYPE(*command_trb) != XHCI_TRB_TYPE_NO_OP_CMD) {
    304414                if (code != XHCI_TRBC_SUCCESS) {
    305415                        report_error(code);
    306                         xhci_dump_trb(command);
     416                        xhci_dump_trb(command_trb);
    307417                }
    308418        }
    309419
    310         switch (TRB_TYPE(*command)) {
     420        switch (TRB_TYPE(*command_trb)) {
    311421        case XHCI_TRB_TYPE_NO_OP_CMD:
    312422                assert(code = XHCI_TRBC_TRB_ERROR);
    313                 return EOK;
     423                break;
    314424        case XHCI_TRB_TYPE_ENABLE_SLOT_CMD:
    315                 return EOK;
     425                break;
    316426        case XHCI_TRB_TYPE_DISABLE_SLOT_CMD:
    317                 return EOK;
     427                break;
    318428        case XHCI_TRB_TYPE_ADDRESS_DEVICE_CMD:
    319                 return EOK;
     429                break;
    320430        case XHCI_TRB_TYPE_CONFIGURE_ENDPOINT_CMD:
    321                 return EOK;
     431                break;
    322432        case XHCI_TRB_TYPE_EVALUATE_CONTEXT_CMD:
    323                 return EOK;
     433                break;
    324434        case XHCI_TRB_TYPE_RESET_ENDPOINT_CMD:
    325                 return EOK;
     435                break;
    326436        case XHCI_TRB_TYPE_STOP_ENDPOINT_CMD:
    327437                // Note: If the endpoint was in the middle of a transfer, then the xHC
    328438                //       will add a Transfer TRB before the Event TRB, research that and
    329439                //       handle it appropriately!
    330                 return EOK;
     440                break;
    331441        case XHCI_TRB_TYPE_RESET_DEVICE_CMD:
    332                 return EOK;
     442                break;
    333443        default:
    334444                usb_log_debug2("Unsupported command trb.");
    335                 xhci_dump_trb(command);
     445                xhci_dump_trb(command_trb);
     446
     447                command->completed = true;
    336448                return ENAK;
    337449        }
     450
     451        command->completed = true;
     452
     453        if (!command->has_owner)
     454                xhci_free_command(command);
     455
     456        return EOK;
    338457}
    339458
  • uspace/drv/bus/usb/xhci/commands.h

    r9af3281 r110d795  
    3737#define XHCI_COMMANDS_H
    3838
     39#include <adt/list.h>
     40#include <stdbool.h>
     41
    3942typedef struct xhci_hc xhci_hc_t;
    4043typedef struct xhci_trb xhci_trb_t;
    4144typedef struct xhci_input_ctx xhci_input_ctx_t;
    4245
    43 int xhci_send_no_op_command(xhci_hc_t *);
    44 int xhci_send_enable_slot_command(xhci_hc_t *);
    45 int xhci_send_disable_slot_command(xhci_hc_t *, uint32_t);
    46 int xhci_send_address_device_command(xhci_hc_t *, uint32_t, xhci_input_ctx_t *);
    47 int xhci_send_configure_endpoint_command(xhci_hc_t *, uint32_t, xhci_input_ctx_t *);
    48 int xhci_send_evaluate_context_command(xhci_hc_t *, uint32_t, xhci_input_ctx_t *);
    49 int xhci_send_reset_endpoint_command(xhci_hc_t *, uint32_t, uint32_t, uint8_t);
    50 int xhci_send_stop_endpoint_command(xhci_hc_t *, uint32_t, uint32_t, uint8_t);
     46typedef struct xhci_command {
     47        link_t link;
     48
     49        xhci_trb_t *trb;
     50        xhci_input_ctx_t *ictx;
     51        uint32_t slot_id;
     52        uint32_t status;
     53
     54        bool completed;
     55        bool has_owner;
     56} xhci_cmd_t;
     57
     58int xhci_init_commands(xhci_hc_t *);
     59int xhci_wait_for_command(xhci_hc_t *, xhci_cmd_t *, uint32_t);
     60xhci_cmd_t *xhci_alloc_command(void);
     61void xhci_free_command(xhci_cmd_t *);
     62
     63int xhci_send_no_op_command(xhci_hc_t *, xhci_cmd_t *);
     64int xhci_send_enable_slot_command(xhci_hc_t *, xhci_cmd_t *);
     65int xhci_send_disable_slot_command(xhci_hc_t *, xhci_cmd_t *);
     66int xhci_send_address_device_command(xhci_hc_t *, xhci_cmd_t *);
     67int xhci_send_configure_endpoint_command(xhci_hc_t *, xhci_cmd_t *);
     68int xhci_send_evaluate_context_command(xhci_hc_t *, xhci_cmd_t *);
     69int xhci_send_reset_endpoint_command(xhci_hc_t *, xhci_cmd_t *, uint32_t, uint8_t);
     70int xhci_send_stop_endpoint_command(xhci_hc_t *, xhci_cmd_t *, uint32_t, uint8_t);
    5171// TODO: Set dequeue ptr (section 4.6.10).
    52 int xhci_send_reset_device_command(xhci_hc_t *, uint32_t);
     72int xhci_send_reset_device_command(xhci_hc_t *, xhci_cmd_t *);
    5373// TODO: Force event (optional normative, for VMM, section 4.6.12).
    5474// TODO: Negotiate bandwidth (optional normative, section 4.6.13).
  • uspace/drv/bus/usb/xhci/hc.h

    r9af3281 r110d795  
    7373        unsigned max_slots;
    7474        bool ac64;
     75
     76        /* Command list */
     77        list_t commands;
    7578} xhci_hc_t;
    7679
Note: See TracChangeset for help on using the changeset viewer.