Changeset 2be477d5 in mainline for uspace/drv/bus/usb/ehci/ehci_rh.c


Ignore:
Timestamp:
2014-01-19T06:26:14Z (10 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
bd41b192
Parents:
4ee5272
Message:

ehci: Implement EHCI RH routines.

untested. reste signalling requires running hc anyway.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ehci/ehci_rh.c

    r4ee5272 r2be477d5  
    116116        ehci_rh_hub_desc_init(instance, EHCI_RD(caps->hcsparams));
    117117        instance->unfinished_interrupt_transfer = NULL;
     118
    118119        return virthub_base_init(&instance->base, name, &ops, instance,
    119120            NULL, &instance->hub_descriptor.header, HUB_STATUS_CHANGE_PIPE);
     
    206207        if (uint16_usb2host(setup_packet->length) != 4)
    207208                return ESTALL;
     209        /* ECHI RH does not report global OC, and local power is always good */
    208210        const uint32_t val = 0;
    209         //TODO: implement
    210211        memcpy(data, &val, sizeof(val));
    211212        *act_size = sizeof(val);
     
    231232         * Chapter 11.16.2 specifies that only C_HUB_LOCAL_POWER and
    232233         * C_HUB_OVER_CURRENT are supported.
    233          * C_HUB_LOCAL_POWER is not supported
    234          * because root hubs do not support local power status feature.
    235          * C_HUB_OVER_CURRENT is represented by EHCI RHS_OCIC_FLAG.
    236          * (EHCI pg. 127)
     234         * C_HUB_LOCAL_POWER is not supported because root hubs do not support
     235         * local power status feature.
     236         * EHCI RH does not report global OC condition either
    237237         */
    238         const unsigned feature = uint16_usb2host(setup_packet->value);
    239         if (feature == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
    240                 //TODO: Implement
    241 //              EHCI_WR(hub->registers->rh_status, RHS_OCIC_FLAG);
    242         }
    243         return EOK;
     238        return ESTALL;
    244239}
    245240
     
    262257                return EINVAL;
    263258
    264         const uint32_t status = 0;
    265         // TODO: Implement
    266         //EHCI_RD(hub->registers->rh_port_status[port]);
     259        const uint32_t reg = EHCI_RD(hub->registers->portsc[port]);
     260        const uint32_t status = uint32_host2usb(0 |
     261            (reg & USB_PORTSC_CONNECT_FLAG) ? (1 << 0) : 0 |
     262            (reg & USB_PORTSC_ENABLED_FLAG) ? (1 << 1) : 0 |
     263            (reg & USB_PORTSC_SUSPEND_FLAG) ? (1 << 2) : 0 |
     264            (reg & USB_PORTSC_OC_ACTIVE_FLAG) ? (1 << 3) : 0 |
     265            (reg & USB_PORTSC_PORT_RESET_FLAG) ? (1 << 4) : 0 |
     266            (reg & USB_PORTSC_PORT_POWER_FLAG) ? (1 << 8) : 0 |
     267            ((reg & USB_PORTSC_LINE_STATUS_MASK) == USB_PORTSC_LINE_STATUS_K) ?
     268                (1 << 9) : 0 |
     269            (reg & USB_PORTSC_PORT_OWNER_FLAG) ? (1 << 10) : 0 |
     270            (reg & USB_PORTSC_PORT_TEST_MASK) ? (1 << 11) : 0 |
     271            (reg & USB_PORTSC_INDICATOR_MASK) ? (1 << 12) : 0)
     272        ;
     273        //TODO: use hub status flags here
    267274        memcpy(data, &status, sizeof(status));
    268275        *act_size = sizeof(status);
     
    290297        {
    291298        case USB_HUB_FEATURE_PORT_POWER:          /*8*/
    292                 {
    293 //                      EHCI_WR(hub->registers->rh_port_status[port],
    294 //                          RHPS_CLEAR_PORT_POWER);
    295 //                          TODO: Implement
    296                         return EOK;
    297                 }
     299                EHCI_CLR(hub->registers->portsc[port],
     300                    USB_PORTSC_PORT_POWER_FLAG);
     301                return EOK;
    298302
    299303        case USB_HUB_FEATURE_PORT_ENABLE:         /*1*/
    300 //              EHCI_WR(hub->registers->rh_port_status[port],
    301 //                  RHPS_CLEAR_PORT_ENABLE);
     304                EHCI_CLR(hub->registers->portsc[port],
     305                    USB_PORTSC_ENABLED_FLAG);
    302306                return EOK;
    303307
    304308        case USB_HUB_FEATURE_PORT_SUSPEND:        /*2*/
    305 //              EHCI_WR(hub->registers->rh_port_status[port],
    306 //                  RHPS_CLEAR_PORT_SUSPEND);
     309                /* If not in suspend it's noop */
     310                if ((EHCI_RD(hub->registers->portsc[port]) &
     311                    USB_PORTSC_SUSPEND_FLAG) == 0)
     312                    return EOK;
     313                /* Host driven resume */
     314                EHCI_SET(hub->registers->portsc[port],
     315                    USB_PORTSC_RESUME_FLAG);
     316                async_usleep(20000);
     317                EHCI_CLR(hub->registers->portsc[port],
     318                    USB_PORTSC_RESUME_FLAG);
    307319                return EOK;
    308320
    309321        case USB_HUB_FEATURE_C_PORT_CONNECTION:   /*16*/
     322                EHCI_SET(hub->registers->portsc[port],
     323                    USB_PORTSC_CONNECT_CH_FLAG);
     324                return EOK;
    310325        case USB_HUB_FEATURE_C_PORT_ENABLE:       /*17*/
     326                EHCI_SET(hub->registers->portsc[port],
     327                    USB_PORTSC_CONNECT_CH_FLAG);
     328                return EOK;
     329        case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: /*19*/
     330                EHCI_SET(hub->registers->portsc[port],
     331                    USB_PORTSC_OC_CHANGE_FLAG);
     332                return EOK;
    311333        case USB_HUB_FEATURE_C_PORT_SUSPEND:      /*18*/
    312         case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: /*19*/
    313334        case USB_HUB_FEATURE_C_PORT_RESET:        /*20*/
    314                 usb_log_debug2("Clearing port C_CONNECTION, C_ENABLE, "
    315                     "C_SUSPEND, C_OC or C_RESET on port %"PRIu16".\n", port);
    316                 /* Bit offsets correspond to the feature number */
    317 //              EHCI_WR(hub->registers->rh_port_status[port],
    318 //                  1 << feature);
     335                //TODO these are not represented in hw, think of something
    319336                return EOK;
    320337
     
    341358        const unsigned feature = uint16_usb2host(setup_packet->value);
    342359        switch (feature) {
     360        case USB_HUB_FEATURE_PORT_ENABLE:  /*1*/
     361                EHCI_SET(hub->registers->portsc[port],
     362                    USB_PORTSC_ENABLED_FLAG);
     363                return EOK;
     364        case USB_HUB_FEATURE_PORT_SUSPEND: /*2*/
     365                EHCI_SET(hub->registers->portsc[port],
     366                    USB_PORTSC_SUSPEND_FLAG);
     367                return EOK;
     368        case USB_HUB_FEATURE_PORT_RESET:   /*4*/
     369                EHCI_SET(hub->registers->portsc[port],
     370                    USB_PORTSC_PORT_RESET_FLAG);
     371                async_usleep(50000);
     372                EHCI_CLR(hub->registers->portsc[port],
     373                    USB_PORTSC_PORT_RESET_FLAG);
     374                /* wait for reset to complete */
     375                while (EHCI_RD(hub->registers->portsc[port]) &
     376                    USB_PORTSC_PORT_RESET_FLAG);
     377                /* Handle port ownership, if the port is not enabled
     378                 * after reset it's a full speed device */
     379                if (!(EHCI_RD(hub->registers->portsc[port]) &
     380                    USB_PORTSC_ENABLED_FLAG))
     381                        EHCI_CLR(hub->registers->portsc[port],
     382                            USB_PORTSC_PORT_OWNER_FLAG);
     383
     384                return EOK;
    343385        case USB_HUB_FEATURE_PORT_POWER:   /*8*/
    344         {
    345                 /* No power switching */
    346 //              if (rhda & RHDA_NPS_FLAG)
    347                         return EOK;
    348                 /* Ganged power switching, one port powers all */
    349 //              if (!(rhda & RHDA_PSM_FLAG)) {
    350 //                      EHCI_WR(hub->registers->rh_status,RHS_SET_GLOBAL_POWER);
    351 //                      return EOK;
    352 //              }
    353         }
    354         /* Fall through, for per port power */
    355         case USB_HUB_FEATURE_PORT_ENABLE:  /*1*/
    356         case USB_HUB_FEATURE_PORT_SUSPEND: /*2*/
    357         case USB_HUB_FEATURE_PORT_RESET:   /*4*/
    358                 usb_log_debug2("Setting port POWER, ENABLE, SUSPEND or RESET "
    359                     "on port %"PRIu16".\n", port);
    360                 /* Bit offsets correspond to the feature number */
    361 //              EHCI_WR(hub->registers->rh_port_status[port], 1 << feature);
     386                EHCI_SET(hub->registers->portsc[port],
     387                    USB_PORTSC_PORT_POWER_FLAG);
    362388                return EOK;
    363389        default:
     
    389415
    390416        uint16_t mask = 0;
    391 
    392         /* Only local power source change and over-current change can happen */
    393 //      if (EHCI_RD(hub->registers->rh_status) & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
    394 //              mask |= 1;
    395 //      }
    396 
    397         for (unsigned port = 1; port <= hub->port_count; ++port) {
     417        for (unsigned port = 0; port < hub->port_count; ++port) {
    398418                /* Write-clean bits are those that indicate change */
    399 //              if (EHCI_RD(hub->registers->rh_port_status[port - 1])
    400 //                  & RHPS_CHANGE_WC_MASK) {
    401 //                      mask |= (1 << port);
    402 //              }
     419                uint32_t status = EHCI_RD(hub->registers->portsc[port]);
     420                if (status & USB_PORTSC_WC_MASK) {
     421                        /* Ignore new LS device */
     422                        if ((status & USB_PORTSC_CONNECT_CH_FLAG) &&
     423                            (status & USB_PORTSC_LINE_STATUS_MASK) ==
     424                                USB_PORTSC_LINE_STATUS_K)
     425                                EHCI_CLR(hub->registers->portsc[port],
     426                                    USB_PORTSC_PORT_OWNER_FLAG);
     427                        else
     428                                mask |= (2 << port);
     429                }
    403430        }
    404431
Note: See TracChangeset for help on using the changeset viewer.