Ignore:
File:
1 edited

Legend:

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

    r76fbd9a r827ec41  
    3333 */
    3434#include <assert.h>
    35 #include <byteorder.h>
    3635#include <errno.h>
    3736#include <str_error.h>
    3837#include <fibril_synch.h>
    3938
    40 #include <usb/usb.h>
    4139#include <usb/debug.h>
    4240#include <usb/dev/request.h>
    4341#include <usb/classes/hub.h>
    4442
     43#include "root_hub.h"
    4544#include <usb/classes/classes.h>
    4645#include <usb/classes/hub.h>
    4746#include <usb/dev/driver.h>
    4847#include "ohci_regs.h"
    49 #include "root_hub.h"
    5048
    5149/**
     
    124122{
    125123        assert(request);
    126         usb_log_debug("Sending interrupt vector(%zu) %hhx:%hhx.\n",
    127             size, ((uint8_t*)&mask)[0], ((uint8_t*)&mask)[1]);
    128124        usb_transfer_batch_finish_error(request, &mask, size, EOK);
    129125        usb_transfer_batch_destroy(request);
     
    154150
    155151        instance->registers = regs;
    156         instance->port_count = OHCI_RD(regs->rh_desc_a) & RHDA_NDS_MASK;
    157         usb_log_debug2("rh_desc_a: %x.\n", OHCI_RD(regs->rh_desc_a));
     152        instance->port_count =
     153            (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
    158154        if (instance->port_count > 15) {
    159155                usb_log_warning("OHCI specification does not allow more than 15"
     
    167163
    168164#if defined OHCI_POWER_SWITCH_no
    169         usb_log_debug("OHCI rh: Set power mode to no power switching.\n");
    170165        /* Set port power mode to no power-switching. (always on) */
    171         OHCI_SET(regs->rh_desc_a, RHDA_NPS_FLAG);
     166        instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
    172167
    173168        /* Set to no over-current reporting */
    174         OHCI_SET(regs->rh_desc_a, RHDA_NOCP_FLAG);
     169        instance->registers->rh_desc_a |= RHDA_NOCP_FLAG;
    175170
    176171#elif defined OHCI_POWER_SWITCH_ganged
    177         usb_log_debug("OHCI rh: Set power mode to ganged power switching.\n");
    178         /* Set port power mode to ganged power-switching. */
    179         OHCI_CLR(regs->rh_desc_a, RHDA_NPS_FLAG);
    180         OHCI_CLR(regs->rh_desc_a, RHDA_PSM_FLAG);
    181 
    182         /* Turn off power (hub driver will turn this back on)*/
    183         OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER);
     172        /* Set port power mode to no ganged power-switching. */
     173        instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG;
     174        instance->registers->rh_desc_a &= ~RHDA_PSM_FLAG;
     175        instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
    184176
    185177        /* Set to global over-current */
    186         OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG);
    187         OHCI_CLR(regs->rh_desc_a, RHDA_OCPM_FLAG);
     178        instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
     179        instance->registers->rh_desc_a &= ~RHDA_OCPM_FLAG;
    188180#else
    189         usb_log_debug("OHCI rh: Set power mode to per-port power switching.\n");
    190         /* Set port power mode to per port power-switching. */
    191         OHCI_CLR(regs->rh_desc_a, RHDA_NPS_FLAG);
    192         OHCI_SET(regs->rh_desc_a, RHDA_PSM_FLAG);
     181        /* Set port power mode to no per port power-switching. */
     182        instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG;
     183        instance->registers->rh_desc_a |= RHDA_PSM_FLAG;
    193184
    194185        /* Control all ports by global switch and turn them off */
    195         OHCI_CLR(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT);
    196         OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER);
     186        instance->registers->rh_desc_b &= (RHDB_PCC_MASK << RHDB_PCC_SHIFT);
     187        instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
    197188
    198189        /* Return control to per port state */
    199         OHCI_SET(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT);
     190        instance->registers->rh_desc_b |=
     191                ((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT;
    200192
    201193        /* Set per port over-current */
    202         OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG);
    203         OHCI_SET(regs->rh_desc_a, RHDA_OCPM_FLAG);
     194        instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
     195        instance->registers->rh_desc_a |= RHDA_OCPM_FLAG;
    204196#endif
    205197
     
    210202            instance->port_count);
    211203}
    212 
     204/*----------------------------------------------------------------------------*/
    213205/**
    214206 * Process root hub request.
     
    234226                fibril_mutex_lock(&instance->guard);
    235227                assert(instance->unfinished_interrupt_transfer == NULL);
    236                 const uint16_t mask = create_interrupt_mask(instance);
     228                uint16_t mask = create_interrupt_mask(instance);
    237229                if (mask == 0) {
    238                         usb_log_debug("No changes(%hx)...\n", mask);
     230                        usb_log_debug("No changes...\n");
    239231                        instance->unfinished_interrupt_transfer = request;
    240232                } else {
     
    251243        }
    252244}
    253 
     245/*----------------------------------------------------------------------------*/
    254246/**
    255247 * Process interrupt on a hub device.
     
    265257        if (instance->unfinished_interrupt_transfer) {
    266258                usb_log_debug("Finalizing interrupt transfer\n");
    267                 const uint16_t mask = create_interrupt_mask(instance);
     259                uint16_t mask = create_interrupt_mask(instance);
    268260                interrupt_request(instance->unfinished_interrupt_transfer,
    269261                    mask, instance->interrupt_mask_size);
     
    272264        fibril_mutex_unlock(&instance->guard);
    273265}
    274 
     266/*----------------------------------------------------------------------------*/
    275267/**
    276268 * Create hub descriptor.
     
    290282        instance->hub_descriptor_size = size;
    291283
    292         const uint32_t hub_desc = OHCI_RD(instance->registers->rh_desc_a);
    293         const uint32_t port_desc = OHCI_RD(instance->registers->rh_desc_b);
     284        uint32_t hub_desc = instance->registers->rh_desc_a;
     285        uint32_t port_desc = instance->registers->rh_desc_b;
    294286
    295287        /* bDescLength */
     
    313305        instance->descriptors.hub[4] = 0;
    314306        /* bPwrOn2PwrGood */
    315         instance->descriptors.hub[5] = hub_desc >> RHDA_POTPGT_SHIFT;
     307        instance->descriptors.hub[5] =
     308            (hub_desc >> RHDA_POTPGT_SHIFT) & RHDA_POTPGT_MASK;
    316309        /* bHubContrCurrent, root hubs don't need no power. */
    317310        instance->descriptors.hub[6] = 0;
    318311
    319312        /* Device Removable and some legacy 1.0 stuff*/
    320         instance->descriptors.hub[7] = (port_desc >> RHDB_DR_SHIFT) & 0xff;
     313        instance->descriptors.hub[7] =
     314            (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK & 0xff;
    321315        instance->descriptors.hub[8] = 0xff;
    322316        if (instance->interrupt_mask_size == 2) {
    323317                instance->descriptors.hub[8] =
    324                     (port_desc >> RHDB_DR_SHIFT) >> 8;
     318                    (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK >> 8;
    325319                instance->descriptors.hub[9]  = 0xff;
    326320                instance->descriptors.hub[10] = 0xff;
    327321        }
    328322}
    329 
     323/*----------------------------------------------------------------------------*/
    330324/** Initialize hub descriptors.
    331325 *
     
    347341            instance->interrupt_mask_size;
    348342
    349         instance->descriptors.configuration.total_length = uint16_host2usb(
     343        instance->descriptors.configuration.total_length =
    350344            sizeof(usb_standard_configuration_descriptor_t) +
    351345            sizeof(usb_standard_endpoint_descriptor_t) +
    352346            sizeof(usb_standard_interface_descriptor_t) +
    353             instance->hub_descriptor_size);
    354 }
    355 
     347            instance->hub_descriptor_size;
     348}
     349/*----------------------------------------------------------------------------*/
    356350/**
    357351 * Create bitmap of changes to answer status interrupt.
     
    370364
    371365        /* Only local power source change and over-current change can happen */
    372         if (OHCI_RD(instance->registers->rh_status)
    373             & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
     366        if (instance->registers->rh_status & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
    374367                mask |= 1;
    375368        }
    376369        for (size_t port = 1; port <= instance->port_count; ++port) {
    377370                /* Write-clean bits are those that indicate change */
    378                 if (OHCI_RD(instance->registers->rh_port_status[port - 1])
    379                     & RHPS_CHANGE_WC_MASK) {
     371                if (RHPS_CHANGE_WC_MASK
     372                    & instance->registers->rh_port_status[port - 1]) {
     373
    380374                        mask |= (1 << port);
    381375                }
    382376        }
    383         usb_log_debug2("OHCI root hub interrupt mask: %hx.\n", mask);
    384         return uint16_host2usb(mask);
    385 }
    386 
     377        /* USB is little endian */
     378        return host2uint32_t_le(mask);
     379}
     380/*----------------------------------------------------------------------------*/
    387381/**
    388382 * Create answer to status request.
     
    402396        usb_device_request_setup_packet_t *request_packet =
    403397            (usb_device_request_setup_packet_t*)request->setup_buffer;
    404 
    405         const uint16_t index = uint16_usb2host(request_packet->index);
    406398
    407399        switch (request_packet->request_type)
     
    414406                        TRANSFER_END(request, EOVERFLOW);
    415407                } else {
    416                         const uint32_t data =
    417                             OHCI_RD(instance->registers->rh_status) &
    418                                 (RHS_LPS_FLAG | RHS_LPSC_FLAG
    419                                     | RHS_OCI_FLAG | RHS_OCIC_FLAG);
     408                        uint32_t data = instance->registers->rh_status &
     409                            (RHS_LPS_FLAG | RHS_LPSC_FLAG
     410                                | RHS_OCI_FLAG | RHS_OCIC_FLAG);
    420411                        TRANSFER_END_DATA(request, &data, sizeof(data));
    421412                }
     
    429420                        TRANSFER_END(request, EOVERFLOW);
    430421                } else {
    431                         const unsigned port = index;
     422                        unsigned port = request_packet->index;
    432423                        if (port < 1 || port > instance->port_count)
    433424                                TRANSFER_END(request, EINVAL);
    434                         /* Register format matches the format of port status
    435                          * field */
    436                         const uint32_t data = uint32_usb2host(OHCI_RD(
    437                             instance->registers->rh_port_status[port - 1]));
     425
     426                        uint32_t data =
     427                            instance->registers->rh_port_status[port - 1];
    438428                        TRANSFER_END_DATA(request, &data, sizeof(data));
    439429                }
     
    444434                        TRANSFER_END(request, EOVERFLOW);
    445435                } else {
    446                         const uint16_t data =
     436                        uint16_t data =
    447437                            uint16_host2usb(USB_DEVICE_STATUS_SELF_POWERED);
    448438                        TRANSFER_END_DATA(request, &data, sizeof(data));
     
    451441        case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE):
    452442                /* Hubs are allowed to have only one interface */
    453                 if (index != 0)
     443                if (request_packet->index != 0)
    454444                        TRANSFER_END(request, EINVAL);
    455445                /* Fall through, as the answer will be the same: 0x0000 */
    456446        case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT):
    457447                /* Endpoint 0 (default control) and 1 (interrupt) */
    458                 if (index >= 2)
     448                if (request_packet->index >= 2)
    459449                        TRANSFER_END(request, EINVAL);
    460450
     
    465455                } else {
    466456                        /* Endpoints are OK. (We don't halt) */
    467                         const uint16_t data = 0;
     457                        uint16_t data = 0;
    468458                        TRANSFER_END_DATA(request, &data, sizeof(data));
    469459                }
     
    475465
    476466}
    477 
     467/*----------------------------------------------------------------------------*/
    478468/**
    479469 * Create answer to a descriptor request.
     
    492482        usb_device_request_setup_packet_t *setup_request =
    493483            (usb_device_request_setup_packet_t *) request->setup_buffer;
    494         /* "The wValue field specifies the descriptor type in the high byte
    495          * and the descriptor index in the low byte (refer to Table 9-5)." */
    496         const int desc_type = uint16_usb2host(setup_request->value) >> 8;
    497         switch (desc_type)
     484        uint16_t setup_request_value = setup_request->value_high;
     485        switch (setup_request_value)
    498486        {
    499487        case USB_DESCTYPE_HUB:
     
    542530                    setup_request->value,
    543531                    setup_request->request_type, setup_request->request,
    544                     desc_type, setup_request->index,
     532                    setup_request_value, setup_request->index,
    545533                    setup_request->length);
    546534                TRANSFER_END(request, EINVAL);
     
    549537        TRANSFER_END(request, ENOTSUP);
    550538}
    551 
     539/*----------------------------------------------------------------------------*/
    552540/**
    553541 * process feature-enabling request on hub
     
    568556        switch (feature)
    569557        {
    570         case USB_HUB_FEATURE_PORT_POWER:   /*8*/
    571                 {
    572                         const uint32_t rhda =
    573                             OHCI_RD(instance->registers->rh_desc_a);
    574                         /* No power switching */
    575                         if (rhda & RHDA_NPS_FLAG)
    576                                 return EOK;
    577                         /* Ganged power switching, one port powers all */
    578                         if (!(rhda & RHDA_PSM_FLAG)) {
    579                                 OHCI_WR(instance->registers->rh_status,
    580                                     RHS_SET_GLOBAL_POWER);
    581                                 return EOK;
    582                         }
     558        case USB_HUB_FEATURE_PORT_POWER:   //8
     559                /* No power switching */
     560                if (instance->registers->rh_desc_a & RHDA_NPS_FLAG)
     561                        return EOK;
     562                /* Ganged power switching */
     563                if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) {
     564                        instance->registers->rh_status = RHS_SET_GLOBAL_POWER;
     565                        return EOK;
    583566                }
    584                         /* Fall through */
    585         case USB_HUB_FEATURE_PORT_ENABLE:  /*1*/
    586         case USB_HUB_FEATURE_PORT_SUSPEND: /*2*/
    587         case USB_HUB_FEATURE_PORT_RESET:   /*4*/
    588                 usb_log_debug2("Setting port POWER, ENABLE, SUSPEND or RESET "
    589                     "on port %zu.\n", port);
    590                 OHCI_WR(instance->registers->rh_port_status[port - 1],
    591                     1 << feature);
     567        case USB_HUB_FEATURE_PORT_ENABLE:  //1
     568        case USB_HUB_FEATURE_PORT_SUSPEND: //2
     569        case USB_HUB_FEATURE_PORT_RESET:   //4
     570                /* Nice thing is that these shifts correspond to the position
     571                 * of control bits in register */
     572                instance->registers->rh_port_status[port - 1] = (1 << feature);
    592573                return EOK;
    593574        default:
     
    595576        }
    596577}
    597 
     578/*----------------------------------------------------------------------------*/
    598579/**
    599580 * Process feature clear request.
     
    615596        switch (feature)
    616597        {
    617         case USB_HUB_FEATURE_PORT_POWER:          /*8*/
    618                 {
    619                         const uint32_t rhda =
    620                             OHCI_RD(instance->registers->rh_desc_a);
    621                         /* No power switching */
    622                         if (rhda & RHDA_NPS_FLAG)
    623                                 return ENOTSUP;
    624                         /* Ganged power switching, one port powers all */
    625                         if (!(rhda & RHDA_PSM_FLAG)) {
    626                                 OHCI_WR(instance->registers->rh_status,
    627                                     RHS_CLEAR_GLOBAL_POWER);
    628                                 return EOK;
    629                         }
    630                         OHCI_WR(instance->registers->rh_port_status[port - 1],
    631                             RHPS_CLEAR_PORT_POWER);
     598        case USB_HUB_FEATURE_PORT_POWER:          //8
     599                /* No power switching */
     600                if (instance->registers->rh_desc_a & RHDA_NPS_FLAG)
     601                        return ENOTSUP;
     602                /* Ganged power switching */
     603                if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) {
     604                        instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
    632605                        return EOK;
    633606                }
    634 
    635         case USB_HUB_FEATURE_PORT_ENABLE:         /*1*/
    636                 OHCI_WR(instance->registers->rh_port_status[port - 1],
    637                     RHPS_CLEAR_PORT_ENABLE);
     607                instance->registers->rh_port_status[port - 1] =
     608                        RHPS_CLEAR_PORT_POWER;
    638609                return EOK;
    639610
    640         case USB_HUB_FEATURE_PORT_SUSPEND:        /*2*/
    641                 OHCI_WR(instance->registers->rh_port_status[port - 1],
    642                     RHPS_CLEAR_PORT_SUSPEND);
     611        case USB_HUB_FEATURE_PORT_ENABLE:         //1
     612                instance->registers->rh_port_status[port - 1] =
     613                        RHPS_CLEAR_PORT_ENABLE;
    643614                return EOK;
    644615
    645         case USB_HUB_FEATURE_C_PORT_CONNECTION:   /*16*/
    646         case USB_HUB_FEATURE_C_PORT_ENABLE:       /*17*/
    647         case USB_HUB_FEATURE_C_PORT_SUSPEND:      /*18*/
    648         case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: /*19*/
    649         case USB_HUB_FEATURE_C_PORT_RESET:        /*20*/
    650                 usb_log_debug2("Clearing port C_CONNECTION, C_ENABLE, "
    651                     "C_SUSPEND, C_OC or C_RESET on port %zu.\n", port);
    652                 /* Bit offsets correspond to the feature number */
    653                 OHCI_WR(instance->registers->rh_port_status[port - 1],
    654                     1 << feature);
     616        case USB_HUB_FEATURE_PORT_SUSPEND:        //2
     617                instance->registers->rh_port_status[port - 1] =
     618                        RHPS_CLEAR_PORT_SUSPEND;
     619                return EOK;
     620
     621        case USB_HUB_FEATURE_C_PORT_CONNECTION:   //16
     622        case USB_HUB_FEATURE_C_PORT_ENABLE:       //17
     623        case USB_HUB_FEATURE_C_PORT_SUSPEND:      //18
     624        case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: //19
     625        case USB_HUB_FEATURE_C_PORT_RESET:        //20
     626                /* Nice thing is that these shifts correspond to the position
     627                 * of control bits in register */
     628                instance->registers->rh_port_status[port - 1] = (1 << feature);
    655629                return EOK;
    656630
     
    659633        }
    660634}
    661 
     635/*----------------------------------------------------------------------------*/
    662636/**
    663637 * process one of requests that do not request nor carry additional data
     
    680654        case USB_HUB_REQ_TYPE_SET_PORT_FEATURE:
    681655                usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    682                 const int ret = set_feature_port(instance,
     656                int ret = set_feature_port(instance,
    683657                    setup_request->value, setup_request->index);
    684658                TRANSFER_END(request, ret);
     
    697671        }
    698672}
    699 
     673/*----------------------------------------------------------------------------*/
    700674/**
    701675 * process one of requests that do not request nor carry additional data
     
    719693        case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE:
    720694                usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n");
    721                 const int ret = clear_feature_port(instance,
     695                int ret = clear_feature_port(instance,
    722696                    setup_request->value, setup_request->index);
    723697                TRANSFER_END(request, ret);
     
    732706                 * as root hubs do not support local power status feature.
    733707                 * (OHCI pg. 127) */
    734                 if (uint16_usb2host(setup_request->value)
    735                     == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
    736                         OHCI_WR(instance->registers->rh_status, RHS_OCIC_FLAG);
     708                if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
     709                        instance->registers->rh_status = RHS_OCIC_FLAG;
    737710                        TRANSFER_END(request, EOK);
    738711                }
     
    744717        }
    745718}
    746 
     719/*----------------------------------------------------------------------------*/
    747720/**
    748721 * Process hub control request.
     
    798771                if (request->buffer_size == 0)
    799772                        TRANSFER_END(request, EOVERFLOW);
    800                 const uint8_t config = 1;
     773                uint8_t config = 1;
    801774                TRANSFER_END_DATA(request, &config, sizeof(config));
    802775
     
    817790                        TRANSFER_END(request, EINVAL);
    818791
    819                 instance->address = uint16_usb2host(setup_request->value);
     792                instance->address = setup_request->value;
    820793                TRANSFER_END(request, EOK);
    821794
    822795        case USB_DEVREQ_SET_CONFIGURATION:
    823796                usb_log_debug("USB_DEVREQ_SET_CONFIGURATION: %u\n",
    824                     uint16_usb2host(setup_request->value));
     797                    setup_request->value);
    825798                /* We have only one configuration, it's number is 1 */
    826799                if (uint16_usb2host(setup_request->value) != 1)
Note: See TracChangeset for help on using the changeset viewer.