Changeset dcf0597 in mainline


Ignore:
Timestamp:
2017-10-13T17:40:48Z (7 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2297fab
Parents:
063dfe8
Message:

xhci rh: move away from virthub

xHC's root hub is too different from other HCs, that it does not make sense to use usbhub for driving it.

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

Legend:

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

    r063dfe8 rdcf0597  
    425425        XHCI_REG_SET(hc->op_regs, XHCI_OP_RS, 1);
    426426
     427        /* The reset changed status of all ports, and SW originated reason does
     428         * not cause an interrupt.
     429         */
     430        xhci_rh_handle_port_change(&hc->rh);
     431
    427432        return EOK;
    428433}
     
    451456{
    452457        assert(batch);
    453 
    454         /* Check for root hub communication */
    455         if (batch->ep->target.address == xhci_rh_get_address(&hc->rh)) {
    456                 usb_log_debug("XHCI root hub request.\n");
    457                 return xhci_rh_schedule(&hc->rh, batch);
    458         }
    459458
    460459        usb_log_debug2("EP(%d:%d) started %s transfer of size %lu.",
     
    488487static event_handler event_handlers [] = {
    489488        [XHCI_TRB_TYPE_COMMAND_COMPLETION_EVENT] = &xhci_handle_command_completion,
    490         [XHCI_TRB_TYPE_PORT_STATUS_CHANGE_EVENT] = &xhci_handle_port_status_change_event,
     489        [XHCI_TRB_TYPE_PORT_STATUS_CHANGE_EVENT] = &xhci_rh_handle_port_status_change_event,
    491490        [XHCI_TRB_TYPE_TRANSFER_EVENT] = &xhci_handle_transfer_event,
    492491};
     
    559558        status = xhci2host(32, status);
    560559
    561         /* TODO: Figure out how root hub interrupts work. */
    562560        if (status & XHCI_REG_MASK(XHCI_OP_PCD)) {
    563561                usb_log_debug2("Root hub interrupt.");
    564                 xhci_rh_interrupt(&hc->rh);
    565 
     562                xhci_rh_handle_port_change(&hc->rh);
    566563                status &= ~XHCI_REG_MASK(XHCI_OP_PCD);
    567564        }
  • uspace/drv/bus/usb/xhci/rh.c

    r063dfe8 rdcf0597  
    11/*
    2 n * Copyright (c) 2017 Michal Staruch
     2 * Copyright (c) 2017 Michal Staruch
    33 * All rights reserved.
    44 *
     
    4646#include "transfers.h"
    4747
    48 #define USB_MAP_VALUE(a, b) [USB_HUB_FEATURE_##a] = b
    49 #define USB_MAP_XHCI(a, b) USB_MAP_VALUE(a, XHCI_REG_MASK(XHCI_PORT_##b))
    50 
    51 enum {
    52         HUB_STATUS_CHANGE_PIPE = 1,
    53 };
    54 
    55 static usbvirt_device_ops_t ops;
    56 
    5748/* This mask only lists registers, which imply port change. */
    5849static const uint32_t port_change_mask =
     
    7364        rh->max_ports = XHCI_REG_RD(hc->cap_regs, XHCI_CAP_MAX_PORTS);
    7465
    75         usb_hub_descriptor_header_t *header = &rh->hub_descriptor.header;
    76         header->length = sizeof(usb_hub_descriptor_header_t);
    77         header->descriptor_type = USB_DESCTYPE_HUB;
    78         header->port_count = rh->max_ports;
    79         header->characteristics =
    80                     HUB_CHAR_NO_POWER_SWITCH_FLAG | HUB_CHAR_NO_OC_FLAG;
    81         header->power_good_time = 10; /* XHCI section 5.4.9 says 20ms max */
    82         header->max_current = 0;
    83 
    84         return virthub_base_init(&rh->base, "xhci", &ops, rh, NULL,
    85             header, HUB_STATUS_CHANGE_PIPE);
     66        return EOK;
    8667}
    8768
     
    186167// }
    187168
    188 // static int handle_connected_device(xhci_hc_t* hc, xhci_port_regs_t* regs, uint8_t port_id)
    189 // {
    190 //      uint8_t link_state = XHCI_REG_RD(regs, XHCI_PORT_PLS);
    191 //      const xhci_port_speed_t *speed = xhci_get_port_speed(&hc->rh, port_id);
    192 //
    193 //      usb_log_info("Detected new %.4s%u.%u device on port %u.", speed->name, speed->major, speed->minor, port_id);
    194 //
    195 //      if (speed->major == 3) {
    196 //              if(link_state == 0) {
    197 //                      /* USB3 is automatically advanced to enabled. */
    198 //                      return alloc_dev(hc, port_id, 0);
    199 //              }
    200 //              else if (link_state == 5) {
    201 //                      /* USB 3 failed to enable. */
    202 //                      usb_log_error("USB 3 port couldn't be enabled.");
    203 //                      return EAGAIN;
    204 //              }
    205 //              else {
    206 //                      usb_log_error("USB 3 port is in invalid state %u.", link_state);
    207 //                      return EINVAL;
    208 //              }
    209 //      }
    210 //      else {
    211 //              usb_log_debug("USB 2 device attached, issuing reset.");
    212 //              xhci_reset_hub_port(hc, port_id);
    213 //              /*
    214 //                      FIXME: we need to wait for the event triggered by the reset
    215 //                      and then alloc_dev()... can't it be done directly instead of
    216 //                      going around?
    217 //              */
    218 //              return EOK;
    219 //      }
    220 // }
    221 
    222 int xhci_handle_port_status_change_event(xhci_hc_t *hc, xhci_trb_t *trb)
    223 {
    224         int err;
    225 
    226         uint8_t port_id = xhci_get_hub_port(trb);
     169static int handle_connected_device(xhci_rh_t *rh, uint8_t port_id)
     170{
     171        xhci_port_regs_t *regs = &rh->hc->op_regs->portrs[port_id - 1];
     172
     173        uint8_t link_state = XHCI_REG_RD(regs, XHCI_PORT_PLS);
     174        const xhci_port_speed_t *speed = xhci_rh_get_port_speed(rh, port_id);
     175
     176        usb_log_info("Detected new %.4s%u.%u device on port %u.", speed->name, speed->major, speed->minor, port_id);
     177
     178        if (speed->major == 3) {
     179                if (link_state == 0) {
     180                        /* USB3 is automatically advanced to enabled. */
     181                        // return alloc_dev(hc, port_id, 0);
     182                        return ENOTSUP;
     183                }
     184                else if (link_state == 5) {
     185                        /* USB 3 failed to enable. */
     186                        usb_log_error("USB 3 port couldn't be enabled.");
     187                        return EAGAIN;
     188                }
     189                else {
     190                        usb_log_error("USB 3 port is in invalid state %u.", link_state);
     191                        return EINVAL;
     192                }
     193        }
     194        else {
     195                usb_log_debug("USB 2 device attached, issuing reset.");
     196                xhci_rh_reset_port(rh, port_id);
     197                /*
     198                        FIXME: we need to wait for the event triggered by the reset
     199                        and then alloc_dev()... can't it be done directly instead of
     200                        going around?
     201                */
     202                return EOK;
     203        }
     204}
     205
     206/** Handle an incoming Port Change Detected Event.
     207 */
     208int xhci_rh_handle_port_status_change_event(xhci_hc_t *hc, xhci_trb_t *trb)
     209{
     210        uint8_t port_id = XHCI_QWORD_EXTRACT(trb->parameter, 31, 24);
    227211        usb_log_debug("Port status change event detected for port %u.", port_id);
    228212
    229         // Interrupt on the virtual hub status change pipe.
    230         err = xhci_rh_interrupt(&hc->rh);
    231         if (err != EOK) {
    232                 usb_log_warning("Invoking interrupt on virtual hub failed: %s",
    233                     str_error(err));
     213        /**
     214         * We can't be sure that the port change this event announces is the
     215         * only port change that happened (see section 4.19.2 of the xHCI
     216         * specification). Therefore, we just check all ports for changes.
     217         */
     218        xhci_rh_handle_port_change(&hc->rh);
     219
     220        return EOK;
     221}
     222
     223void xhci_rh_handle_port_change(xhci_rh_t *rh)
     224{
     225        for (uint8_t i = 1; i <= rh->max_ports; ++i) {
     226                xhci_port_regs_t *regs = &rh->hc->op_regs->portrs[i - 1];
     227
     228                uint32_t events = XHCI_REG_RD_FIELD(&regs->portsc, 32);
     229                XHCI_REG_WR_FIELD(&regs->portsc, events, 32);
     230
     231                events &= port_change_mask;
     232
     233                if (events & XHCI_REG_MASK(XHCI_PORT_CSC)) {
     234                        usb_log_info("Connected state changed on port %u.", i);
     235                        events &= ~XHCI_REG_MASK(XHCI_PORT_CSC);
     236
     237                        bool connected = XHCI_REG_RD(regs, XHCI_PORT_CCS);
     238                        if (connected)
     239                                handle_connected_device(rh, i);
     240                }
     241
     242                if (events & XHCI_REG_MASK(XHCI_PORT_PEC)) {
     243                        usb_log_info("Port enabled changed on port %u.", i);
     244                        events &= ~XHCI_REG_MASK(XHCI_PORT_PEC);
     245                }
     246
     247                if (events & XHCI_REG_MASK(XHCI_PORT_WRC)) {
     248                        usb_log_info("Warm port reset on port %u completed.", i);
     249                        events &= ~XHCI_REG_MASK(XHCI_PORT_WRC);
     250                }
     251
     252                if (events & XHCI_REG_MASK(XHCI_PORT_OCC)) {
     253                        usb_log_info("Over-current change on port %u.", i);
     254                        events &= ~XHCI_REG_MASK(XHCI_PORT_OCC);
     255                }
     256
     257                if (events & XHCI_REG_MASK(XHCI_PORT_PRC)) {
     258                        usb_log_info("Port reset on port %u completed.", i);
     259                        events &= ~XHCI_REG_MASK(XHCI_PORT_PRC);
     260                }
     261
     262                if (events & XHCI_REG_MASK(XHCI_PORT_PLC)) {
     263                        usb_log_info("Port link state changed on port %u.", i);
     264                        events &= ~XHCI_REG_MASK(XHCI_PORT_PLC);
     265                }
     266
     267                if (events & XHCI_REG_MASK(XHCI_PORT_CEC)) {
     268                        usb_log_info("Port %u failed to configure link.", i);
     269                        events &= ~XHCI_REG_MASK(XHCI_PORT_CEC);
     270                }
     271
     272                if (events) {
     273                        usb_log_warning("Port change (0x%08x) ignored on port %u.", events, i);
     274                }
    234275        }
    235 
    236         return EOK;
    237 }
    238 
    239 const xhci_port_speed_t *xhci_get_port_speed(xhci_rh_t *rh, uint8_t port)
     276       
     277        /**
     278         * Theory:
     279         *
     280         * Although more events could have happened while processing, the PCD
     281         * bit in USBSTS will be set on every change. Because the PCD is
     282         * cleared even before the interrupt is cleared, it is safe to assume
     283         * that this handler will be called again.
     284         *
     285         * But because we could have handled the event in previous run of this
     286         * handler, it is not an error when no event is detected.
     287         *
     288         * Reality:
     289         *
     290         * The PCD bit is never set. TODO Check why the interrupt never carries
     291         * the PCD flag. Possibly repeat the checking until we're sure the
     292         * PSCEG is 0 - check section 4.19.2 of the xHCI spec.
     293         */
     294}
     295
     296const xhci_port_speed_t *xhci_rh_get_port_speed(xhci_rh_t *rh, uint8_t port)
    240297{
    241298        xhci_port_regs_t *port_regs = &rh->hc->op_regs->portrs[port - 1];
     
    245302}
    246303
    247 int xhci_get_hub_port(xhci_trb_t *trb)
    248 {
    249         assert(trb);
    250         uint8_t port_id = XHCI_QWORD_EXTRACT(trb->parameter, 31, 24);
    251 
    252         return port_id;
    253 }
    254 
    255 int xhci_reset_hub_port(xhci_hc_t* hc, uint8_t port)
     304int xhci_rh_reset_port(xhci_rh_t* rh, uint8_t port)
    256305{
    257306        usb_log_debug2("Resetting port %u.", port);
    258         xhci_port_regs_t *regs = &hc->op_regs->portrs[port-1];
    259         XHCI_REG_WR(regs, XHCI_PORT_PR, 1);
     307        xhci_port_regs_t *regs = &rh->hc->op_regs->portrs[port-1];
     308        XHCI_REG_SET(regs, XHCI_PORT_PR, 1);
    260309
    261310        return EOK;
    262 }
    263 
    264 int xhci_rh_schedule(xhci_rh_t *rh, usb_transfer_batch_t *batch)
    265 {
    266         assert(rh);
    267         assert(batch);
    268         const usb_target_t target = batch->ep->target;
    269         batch->error = virthub_base_request(&rh->base, target,
    270             usb_transfer_batch_direction(batch), (void*)batch->setup_buffer,
    271             batch->buffer, batch->buffer_size, &batch->transfered_size);
    272         if (batch->error == ENAK) {
    273                 /* This is safe because only status change interrupt transfers
    274                  * return NAK. The assertion holds true because the batch
    275                  * existence prevents communication with that ep */
    276                 assert(rh->unfinished_interrupt_transfer == NULL);
    277                 rh->unfinished_interrupt_transfer = batch;
    278         } else {
    279                 usb_transfer_batch_finish(batch, NULL);
    280                 usb_transfer_batch_destroy(batch);
    281         }
    282         return EOK;
    283 }
    284 
    285 int xhci_rh_interrupt(xhci_rh_t *rh)
    286 {
    287         usb_log_debug2("Called xhci_rh_interrupt().");
    288 
    289         /* TODO: atomic swap needed */
    290         usb_transfer_batch_t *batch = rh->unfinished_interrupt_transfer;
    291         rh->unfinished_interrupt_transfer = NULL;
    292         if (batch) {
    293                 const usb_target_t target = batch->ep->target;
    294                 batch->error = virthub_base_request(&rh->base, target,
    295                     usb_transfer_batch_direction(batch),
    296                     (void*)batch->setup_buffer,
    297                     batch->buffer, batch->buffer_size, &batch->transfered_size);
    298                 usb_transfer_batch_finish(batch, NULL);
    299                 usb_transfer_batch_destroy(batch);
    300         }
    301         return EOK;
    302 }
    303 
    304 /** Hub set feature request handler.
    305  * @param device Virtual hub device
    306  * @param setup_packet USB setup stage data.
    307  * @param[out] data destination data buffer, size must be at least
    308  *             setup_packet->length bytes
    309  * @param[out] act_size Sized of the valid response part of the buffer.
    310  * @return Error code.
    311  */
    312 static int req_clear_hub_feature(usbvirt_device_t *device,
    313         const usb_device_request_setup_packet_t *setup_packet,
    314         uint8_t *data, size_t *act_size)
    315 {
    316         /* TODO: Implement me! */
    317         usb_log_debug2("Called req_clear_hub_feature().");
    318         return EOK;
    319 }
    320 
    321 #define XHCI_TO_USB(usb_feat, reg_set, ...) \
    322         (((XHCI_REG_RD(reg_set, ##__VA_ARGS__)) ? 1 : 0) << (usb_feat))
    323 
    324 /** Port status request handler.
    325  * @param device Virtual hub device
    326  * @param setup_packet USB setup stage data.
    327  * @param[out] data destination data buffer, size must be at least
    328  *             setup_packet->length bytes
    329  * @param[out] act_size Sized of the valid response part of the buffer.
    330  * @return Error code.
    331  */
    332 static int req_get_port_status(usbvirt_device_t *device,
    333         const usb_device_request_setup_packet_t *setup_packet,
    334         uint8_t *data, size_t *act_size)
    335 {
    336         xhci_rh_t *hub = virthub_get_data(device);
    337         assert(hub);
    338 
    339         if (!setup_packet->index || setup_packet->index > hub->max_ports) {
    340                 return ESTALL;
    341         }
    342 
    343         /* The index is 1-based. */
    344         xhci_port_regs_t* regs = &hub->hc->op_regs->portrs[setup_packet->index - 1];
    345 
    346         const uint32_t status = uint32_host2usb(
    347             XHCI_TO_USB(USB_HUB_FEATURE_C_PORT_CONNECTION, regs, XHCI_PORT_CSC) |
    348             XHCI_TO_USB(USB_HUB_FEATURE_C_PORT_ENABLE, regs, XHCI_PORT_PEC) |
    349             XHCI_TO_USB(USB_HUB_FEATURE_C_PORT_OVER_CURRENT, regs, XHCI_PORT_OCC) |
    350             XHCI_TO_USB(USB_HUB_FEATURE_C_PORT_RESET, regs, XHCI_PORT_PRC) |
    351             XHCI_TO_USB(USB_HUB_FEATURE_PORT_CONNECTION, regs, XHCI_PORT_CCS) |
    352             XHCI_TO_USB(USB_HUB_FEATURE_PORT_ENABLE, regs, XHCI_PORT_PED) |
    353             XHCI_TO_USB(USB_HUB_FEATURE_PORT_OVER_CURRENT, regs, XHCI_PORT_OCA) |
    354             XHCI_TO_USB(USB_HUB_FEATURE_PORT_RESET, regs, XHCI_PORT_PR) |
    355             XHCI_TO_USB(USB_HUB_FEATURE_PORT_POWER, regs, XHCI_PORT_PP)
    356         );
    357 
    358         usb_log_debug2("RH: GetPortStatus(%hu) = %u.", setup_packet->index,
    359                 uint32_usb2host(status));
    360 
    361         memcpy(data, &status, sizeof(status));
    362         *act_size = sizeof(status);
    363 
    364         return EOK;
    365 }
    366 
    367 /** Port clear feature request handler.
    368  * @param device Virtual hub device
    369  * @param setup_packet USB setup stage data.
    370  * @param[out] data destination data buffer, size must be at least
    371  *             setup_packet->length bytes
    372  * @param[out] act_size Sized of the valid response part of the buffer.
    373  * @return Error code.
    374  */
    375 static int req_clear_port_feature(usbvirt_device_t *device,
    376         const usb_device_request_setup_packet_t *setup_packet,
    377         uint8_t *data, size_t *act_size)
    378 {
    379         xhci_rh_t *hub = virthub_get_data(device);
    380         assert(hub);
    381 
    382         if (!setup_packet->index || setup_packet->index > hub->max_ports) {
    383                 return ESTALL;
    384         }
    385 
    386         /* The index is 1-based. */
    387         xhci_port_regs_t* regs = &hub->hc->op_regs->portrs[setup_packet->index - 1];
    388 
    389         const usb_hub_class_feature_t feature = uint16_usb2host(setup_packet->value);
    390         static const ioport32_t masks[] = {
    391                 USB_MAP_XHCI(C_PORT_CONNECTION, CSC),
    392                 USB_MAP_XHCI(C_PORT_ENABLE, PEC),
    393                 USB_MAP_XHCI(C_PORT_OVER_CURRENT, OCC),
    394                 USB_MAP_XHCI(C_PORT_RESET, PRC),
    395                 USB_MAP_XHCI(PORT_ENABLE, PED),
    396                 USB_MAP_XHCI(PORT_RESET, PR),
    397                 USB_MAP_XHCI(PORT_POWER, PP)
    398         };
    399 
    400         static const bool is_change[] = {
    401                 USB_MAP_VALUE(C_PORT_CONNECTION, true),
    402                 USB_MAP_VALUE(C_PORT_ENABLE, true),
    403                 USB_MAP_VALUE(C_PORT_OVER_CURRENT, true),
    404                 USB_MAP_VALUE(C_PORT_RESET, true),
    405                 USB_MAP_VALUE(PORT_ENABLE, false),
    406                 USB_MAP_VALUE(PORT_RESET, false),
    407                 USB_MAP_VALUE(PORT_POWER, false)
    408         };
    409 
    410         usb_log_debug2("RH: ClearPortFeature(%hu) = %d.", setup_packet->index,
    411                 feature);
    412 
    413         if (is_change[feature]) {
    414                 /* Clear the register by writing 1. */
    415                 XHCI_REG_SET_FIELD(&regs->portsc, masks[feature], 32);
    416         } else {
    417                 /* Clear the register by writing 0. */
    418                 XHCI_REG_CLR_FIELD(&regs->portsc, masks[feature], 32);
    419         }
    420 
    421         return EOK;
    422 }
    423 
    424 /** Port set feature request handler.
    425  * @param device Virtual hub device
    426  * @param setup_packet USB setup stage data.
    427  * @param[out] data destination data buffer, size must be at least
    428  *             setup_packet->length bytes
    429  * @param[out] act_size Sized of the valid response part of the buffer.
    430  * @return Error code.
    431  */
    432 static int req_set_port_feature(usbvirt_device_t *device,
    433         const usb_device_request_setup_packet_t *setup_packet,
    434         uint8_t *data, size_t *act_size)
    435 {
    436         xhci_rh_t *hub = virthub_get_data(device);
    437         assert(hub);
    438 
    439         if (!setup_packet->index || setup_packet->index > hub->max_ports) {
    440                 return ESTALL;
    441         }
    442 
    443         /* The index is 1-based. */
    444         xhci_port_regs_t* regs = &hub->hc->op_regs->portrs[setup_packet->index - 1];
    445 
    446         const usb_hub_class_feature_t feature = uint16_usb2host(setup_packet->value);
    447         static const ioport32_t masks[] = {
    448                 USB_MAP_XHCI(PORT_ENABLE, PED),
    449                 USB_MAP_XHCI(PORT_RESET, PR),
    450                 USB_MAP_XHCI(PORT_POWER, PP)
    451         };
    452 
    453         usb_log_debug2("RH: SetPortFeature(%hu) = %d.", setup_packet->index,
    454                 feature);
    455 
    456         /* Set the feature in the PIO register. */
    457         XHCI_REG_SET_FIELD(&regs->portsc, masks[feature], 32);
    458 
    459         return EOK;
    460 }
    461 
    462 /** Status change handler.
    463  * @param device Virtual hub device
    464  * @param endpoint Endpoint number
    465  * @param tr_type Transfer type
    466  * @param buffer Response destination
    467  * @param buffer_size Bytes available in buffer
    468  * @param actual_size Size us the used part of the dest buffer.
    469  *
    470  * Produces status mask. Bit 0 indicates hub status change the other bits
    471  * represent port status change.
    472  */
    473 static int req_status_change_handler(usbvirt_device_t *device,
    474         usb_endpoint_t endpoint, usb_transfer_type_t tr_type,
    475         void *buffer, size_t buffer_size, size_t *actual_size)
    476 {
    477         xhci_rh_t *hub = virthub_get_data(device);
    478         assert(hub);
    479 
    480         uint8_t status[STATUS_BYTES(hub->max_ports)];
    481         memset(status, 0, sizeof(status));
    482 
    483         if (buffer_size < sizeof(status))
    484                 return ESTALL;
    485 
    486         bool change = false;
    487         for (size_t i = 1; i <= hub->max_ports; ++i) {
    488                 xhci_port_regs_t *regs = &hub->hc->op_regs->portrs[i - 1];
    489 
    490                 if (XHCI_REG_RD_FIELD(&regs->portsc, 32) & port_change_mask) {
    491                         status[i / 8] |= (1 << (i % 8));
    492                         change = true;
    493                 }
    494         }
    495 
    496         usb_log_debug2("RH: Status change %s", (change ? "occurred" : "did not occur"));
    497         memcpy(buffer, &status, sizeof(status));
    498         *actual_size = sizeof(status);
    499         return change ? EOK : ENAK;
    500311}
    501312
     
    507318}
    508319
    509 /** XHCI root hub request handlers */
    510 static const usbvirt_control_request_handler_t control_transfer_handlers[] = {
    511         {
    512                 STD_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
    513                 .name = "GetDescriptor",
    514                 .callback = virthub_base_get_hub_descriptor,
    515         },
    516         {
    517                 CLASS_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
    518                 .name = "GetDescriptor",
    519                 .callback = virthub_base_get_hub_descriptor,
    520         },
    521         {
    522                 CLASS_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_HUB_REQUEST_GET_DESCRIPTOR),
    523                 .name = "GetHubDescriptor",
    524                 .callback = virthub_base_get_hub_descriptor,
    525         },
    526         {
    527                 CLASS_REQ_IN(USB_REQUEST_RECIPIENT_OTHER, USB_HUB_REQUEST_GET_STATUS),
    528                 .name = "GetPortStatus",
    529                 .callback = req_get_port_status,
    530         },
    531         {
    532                 CLASS_REQ_OUT(USB_REQUEST_RECIPIENT_DEVICE, USB_HUB_REQUEST_CLEAR_FEATURE),
    533                 .name = "ClearHubFeature",
    534                 .callback = req_clear_hub_feature,
    535         },
    536         {
    537                 CLASS_REQ_OUT(USB_REQUEST_RECIPIENT_OTHER, USB_HUB_REQUEST_CLEAR_FEATURE),
    538                 .name = "ClearPortFeature",
    539                 .callback = req_clear_port_feature,
    540         },
    541         {
    542                 CLASS_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_HUB_REQUEST_GET_STATUS),
    543                 .name = "GetHubStatus",
    544                 /* XHCI root hub has no power source,
    545                  * over-current is reported by port */
    546                 .callback = virthub_base_get_null_status,
    547         },
    548         {
    549                 CLASS_REQ_IN(USB_REQUEST_RECIPIENT_OTHER, USB_HUB_REQUEST_GET_STATUS),
    550                 .name = "GetPortStatus",
    551                 .callback = req_get_port_status,
    552         },
    553         {
    554                 CLASS_REQ_OUT(USB_REQUEST_RECIPIENT_DEVICE, USB_HUB_REQUEST_SET_FEATURE),
    555                 .name = "SetHubFeature",
    556                 .callback = req_nop,
    557         },
    558         {
    559                 CLASS_REQ_OUT(USB_REQUEST_RECIPIENT_OTHER, USB_HUB_REQUEST_SET_FEATURE),
    560                 .name = "SetPortFeature",
    561                 .callback = req_set_port_feature,
    562         },
    563         {
    564                 .callback = NULL
    565         }
    566 };
    567 
    568 /** Virtual XHCI root hub ops */
    569 static usbvirt_device_ops_t ops = {
    570         .control = control_transfer_handlers,
    571         .data_in[HUB_STATUS_CHANGE_PIPE] = req_status_change_handler,
    572 };
    573 
    574 
    575320/**
    576321 * @}
  • uspace/drv/bus/usb/xhci/rh.h

    r063dfe8 rdcf0597  
    3838
    3939#include <usb/host/usb_transfer_batch.h>
    40 #include <usbvirt/virthub_base.h>
    4140#include "hw_struct/regs.h"
    4241
    4342typedef struct xhci_hc xhci_hc_t;
    44 
    45 enum {
    46         XHCI_MAX_PORTS = 255,
    47 };
    4843
    4944/**
     
    5853/* XHCI root hub instance */
    5954typedef struct {
    60         /** Virtual hub instance */
    61         virthub_base_t base;
    62 
    6355        /** Host controller */
    6456        xhci_hc_t *hc;
     
    6658        /** Port speeds reported from HC */
    6759        xhci_port_speed_t speeds [16];
    68 
    69         /** USB hub descriptor describing the XHCI root hub */
    70         struct {
    71                 usb_hub_descriptor_header_t header;
    72                 uint8_t rempow[STATUS_BYTES(XHCI_MAX_PORTS) * 2];
    73         } __attribute__((packed)) hub_descriptor;
    7460
    7561        /** Interrupt transfer waiting for an actual interrupt to occur */
     
    8268int xhci_rh_init(xhci_rh_t *, xhci_hc_t *);
    8369int xhci_rh_fini(xhci_rh_t *);
    84 const xhci_port_speed_t *xhci_get_port_speed(xhci_rh_t *, uint8_t);
    85 int xhci_handle_port_status_change_event(xhci_hc_t *, xhci_trb_t *);
    86 int xhci_get_hub_port(xhci_trb_t *);
    87 int xhci_reset_hub_port(xhci_hc_t *, uint8_t);
    88 int xhci_rh_schedule(xhci_rh_t *, usb_transfer_batch_t *);
    89 int xhci_rh_interrupt(xhci_rh_t *);
     70const xhci_port_speed_t *xhci_rh_get_port_speed(xhci_rh_t *, uint8_t);
     71int xhci_rh_reset_port(xhci_rh_t *, uint8_t);
    9072
    91 /** Get XHCI rh address.
    92  *
    93  * @param rh XHCI rh instance.
    94  * @return USB address assigned to the hub.
    95  * Wrapper for virtual hub address
    96  */
    97 static inline usb_address_t xhci_rh_get_address(xhci_rh_t *rh)
    98 {
    99         assert(rh);
    100         return virthub_base_get_address(&rh->base);
    101 }
     73int xhci_rh_handle_port_status_change_event(xhci_hc_t *, xhci_trb_t *);
     74void xhci_rh_handle_port_change(xhci_rh_t *);
    10275
    103 static inline bool xhci_is_usb3_port(xhci_rh_t* rh, uint8_t port)
    104 {
    105         return xhci_get_port_speed(rh, port)->major == 3;
    106 }
    10776#endif
    10877
  • uspace/drv/bus/usb/xhci/transfers.c

    r063dfe8 rdcf0597  
    3636#include <usb/host/utils/malloc32.h>
    3737#include <usb/debug.h>
     38#include <usb/request.h>
    3839#include "endpoint.h"
    3940#include "hc.h"
Note: See TracChangeset for help on using the changeset viewer.