Changeset da68871a in mainline for uspace/drv/bus/usb/ohci/root_hub.c


Ignore:
Timestamp:
2012-08-08T08:46:22Z (12 years ago)
Author:
Adam Hraska <adam.hraska+hos@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
30c0826
Parents:
bc216a0 (diff), 1d01cca (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:

Merged changes from mainline.

File:
1 edited

Legend:

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

    rbc216a0 rda68871a  
    3333 */
    3434#include <assert.h>
     35#include <byteorder.h>
    3536#include <errno.h>
    3637#include <str_error.h>
    3738#include <fibril_synch.h>
    3839
     40#include <usb/usb.h>
    3941#include <usb/debug.h>
    4042#include <usb/dev/request.h>
    4143#include <usb/classes/hub.h>
    4244
    43 #include "root_hub.h"
    4445#include <usb/classes/classes.h>
    4546#include <usb/classes/hub.h>
    4647#include <usb/dev/driver.h>
    4748#include "ohci_regs.h"
     49#include "root_hub.h"
    4850
    4951/**
     
    122124{
    123125        assert(request);
     126        usb_log_debug("Sending interrupt vector(%zu) %hhx:%hhx.\n",
     127            size, ((uint8_t*)&mask)[0], ((uint8_t*)&mask)[1]);
    124128        usb_transfer_batch_finish_error(request, &mask, size, EOK);
    125129        usb_transfer_batch_destroy(request);
     
    150154
    151155        instance->registers = regs;
    152         instance->port_count =
    153             (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
     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));
    154158        if (instance->port_count > 15) {
    155159                usb_log_warning("OHCI specification does not allow more than 15"
     
    163167
    164168#if defined OHCI_POWER_SWITCH_no
     169        usb_log_debug("OHCI rh: Set power mode to no power switching.\n");
    165170        /* Set port power mode to no power-switching. (always on) */
    166         instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
     171        OHCI_SET(regs->rh_desc_a, RHDA_NPS_FLAG);
    167172
    168173        /* Set to no over-current reporting */
    169         instance->registers->rh_desc_a |= RHDA_NOCP_FLAG;
     174        OHCI_SET(regs->rh_desc_a, RHDA_NOCP_FLAG);
    170175
    171176#elif defined OHCI_POWER_SWITCH_ganged
    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;
     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);
    176184
    177185        /* Set to global over-current */
    178         instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
    179         instance->registers->rh_desc_a &= ~RHDA_OCPM_FLAG;
     186        OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG);
     187        OHCI_CLR(regs->rh_desc_a, RHDA_OCPM_FLAG);
    180188#else
    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;
     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);
    184193
    185194        /* Control all ports by global switch and turn them off */
    186         instance->registers->rh_desc_b &= (RHDB_PCC_MASK << RHDB_PCC_SHIFT);
    187         instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
     195        OHCI_CLR(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT);
     196        OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER);
    188197
    189198        /* Return control to per port state */
    190         instance->registers->rh_desc_b |=
    191                 ((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT;
     199        OHCI_SET(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT);
    192200
    193201        /* Set per port over-current */
    194         instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
    195         instance->registers->rh_desc_a |= RHDA_OCPM_FLAG;
     202        OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG);
     203        OHCI_SET(regs->rh_desc_a, RHDA_OCPM_FLAG);
    196204#endif
    197205
     
    202210            instance->port_count);
    203211}
    204 /*----------------------------------------------------------------------------*/
     212
    205213/**
    206214 * Process root hub request.
     
    226234                fibril_mutex_lock(&instance->guard);
    227235                assert(instance->unfinished_interrupt_transfer == NULL);
    228                 uint16_t mask = create_interrupt_mask(instance);
     236                const uint16_t mask = create_interrupt_mask(instance);
    229237                if (mask == 0) {
    230                         usb_log_debug("No changes...\n");
     238                        usb_log_debug("No changes(%hx)...\n", mask);
    231239                        instance->unfinished_interrupt_transfer = request;
    232240                } else {
     
    243251        }
    244252}
    245 /*----------------------------------------------------------------------------*/
     253
    246254/**
    247255 * Process interrupt on a hub device.
     
    257265        if (instance->unfinished_interrupt_transfer) {
    258266                usb_log_debug("Finalizing interrupt transfer\n");
    259                 uint16_t mask = create_interrupt_mask(instance);
     267                const uint16_t mask = create_interrupt_mask(instance);
    260268                interrupt_request(instance->unfinished_interrupt_transfer,
    261269                    mask, instance->interrupt_mask_size);
     
    264272        fibril_mutex_unlock(&instance->guard);
    265273}
    266 /*----------------------------------------------------------------------------*/
     274
    267275/**
    268276 * Create hub descriptor.
     
    282290        instance->hub_descriptor_size = size;
    283291
    284         uint32_t hub_desc = instance->registers->rh_desc_a;
    285         uint32_t port_desc = instance->registers->rh_desc_b;
     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);
    286294
    287295        /* bDescLength */
     
    305313        instance->descriptors.hub[4] = 0;
    306314        /* bPwrOn2PwrGood */
    307         instance->descriptors.hub[5] =
    308             (hub_desc >> RHDA_POTPGT_SHIFT) & RHDA_POTPGT_MASK;
     315        instance->descriptors.hub[5] = hub_desc >> RHDA_POTPGT_SHIFT;
    309316        /* bHubContrCurrent, root hubs don't need no power. */
    310317        instance->descriptors.hub[6] = 0;
    311318
    312319        /* Device Removable and some legacy 1.0 stuff*/
    313         instance->descriptors.hub[7] =
    314             (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK & 0xff;
     320        instance->descriptors.hub[7] = (port_desc >> RHDB_DR_SHIFT) & 0xff;
    315321        instance->descriptors.hub[8] = 0xff;
    316322        if (instance->interrupt_mask_size == 2) {
    317323                instance->descriptors.hub[8] =
    318                     (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK >> 8;
     324                    (port_desc >> RHDB_DR_SHIFT) >> 8;
    319325                instance->descriptors.hub[9]  = 0xff;
    320326                instance->descriptors.hub[10] = 0xff;
    321327        }
    322328}
    323 /*----------------------------------------------------------------------------*/
     329
    324330/** Initialize hub descriptors.
    325331 *
     
    341347            instance->interrupt_mask_size;
    342348
    343         instance->descriptors.configuration.total_length =
     349        instance->descriptors.configuration.total_length = uint16_host2usb(
    344350            sizeof(usb_standard_configuration_descriptor_t) +
    345351            sizeof(usb_standard_endpoint_descriptor_t) +
    346352            sizeof(usb_standard_interface_descriptor_t) +
    347             instance->hub_descriptor_size;
    348 }
    349 /*----------------------------------------------------------------------------*/
     353            instance->hub_descriptor_size);
     354}
     355
    350356/**
    351357 * Create bitmap of changes to answer status interrupt.
     
    364370
    365371        /* Only local power source change and over-current change can happen */
    366         if (instance->registers->rh_status & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
     372        if (OHCI_RD(instance->registers->rh_status)
     373            & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
    367374                mask |= 1;
    368375        }
    369376        for (size_t port = 1; port <= instance->port_count; ++port) {
    370377                /* Write-clean bits are those that indicate change */
    371                 if (RHPS_CHANGE_WC_MASK
    372                     & instance->registers->rh_port_status[port - 1]) {
    373 
     378                if (OHCI_RD(instance->registers->rh_port_status[port - 1])
     379                    & RHPS_CHANGE_WC_MASK) {
    374380                        mask |= (1 << port);
    375381                }
    376382        }
    377         /* USB is little endian */
    378         return host2uint32_t_le(mask);
    379 }
    380 /*----------------------------------------------------------------------------*/
     383        usb_log_debug2("OHCI root hub interrupt mask: %hx.\n", mask);
     384        return uint16_host2usb(mask);
     385}
     386
    381387/**
    382388 * Create answer to status request.
     
    396402        usb_device_request_setup_packet_t *request_packet =
    397403            (usb_device_request_setup_packet_t*)request->setup_buffer;
     404
     405        const uint16_t index = uint16_usb2host(request_packet->index);
    398406
    399407        switch (request_packet->request_type)
     
    406414                        TRANSFER_END(request, EOVERFLOW);
    407415                } else {
    408                         uint32_t data = instance->registers->rh_status &
    409                             (RHS_LPS_FLAG | RHS_LPSC_FLAG
    410                                 | RHS_OCI_FLAG | RHS_OCIC_FLAG);
     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);
    411420                        TRANSFER_END_DATA(request, &data, sizeof(data));
    412421                }
     
    420429                        TRANSFER_END(request, EOVERFLOW);
    421430                } else {
    422                         unsigned port = request_packet->index;
     431                        const unsigned port = index;
    423432                        if (port < 1 || port > instance->port_count)
    424433                                TRANSFER_END(request, EINVAL);
    425 
    426                         uint32_t data =
    427                             instance->registers->rh_port_status[port - 1];
     434                        /* Register format matches the format of port status
     435                         * field */
     436                        const uint32_t data = uint32_host2usb(OHCI_RD(
     437                            instance->registers->rh_port_status[port - 1]));
    428438                        TRANSFER_END_DATA(request, &data, sizeof(data));
    429439                }
     
    434444                        TRANSFER_END(request, EOVERFLOW);
    435445                } else {
    436                         uint16_t data =
     446                        const uint16_t data =
    437447                            uint16_host2usb(USB_DEVICE_STATUS_SELF_POWERED);
    438448                        TRANSFER_END_DATA(request, &data, sizeof(data));
     
    441451        case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE):
    442452                /* Hubs are allowed to have only one interface */
    443                 if (request_packet->index != 0)
     453                if (index != 0)
    444454                        TRANSFER_END(request, EINVAL);
    445455                /* Fall through, as the answer will be the same: 0x0000 */
    446456        case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT):
    447457                /* Endpoint 0 (default control) and 1 (interrupt) */
    448                 if (request_packet->index >= 2)
     458                if (index >= 2)
    449459                        TRANSFER_END(request, EINVAL);
    450460
     
    455465                } else {
    456466                        /* Endpoints are OK. (We don't halt) */
    457                         uint16_t data = 0;
     467                        const uint16_t data = 0;
    458468                        TRANSFER_END_DATA(request, &data, sizeof(data));
    459469                }
     
    465475
    466476}
    467 /*----------------------------------------------------------------------------*/
     477
    468478/**
    469479 * Create answer to a descriptor request.
     
    482492        usb_device_request_setup_packet_t *setup_request =
    483493            (usb_device_request_setup_packet_t *) request->setup_buffer;
    484         uint16_t setup_request_value = setup_request->value_high;
    485         switch (setup_request_value)
     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)
    486498        {
    487499        case USB_DESCTYPE_HUB:
     
    530542                    setup_request->value,
    531543                    setup_request->request_type, setup_request->request,
    532                     setup_request_value, setup_request->index,
     544                    desc_type, setup_request->index,
    533545                    setup_request->length);
    534546                TRANSFER_END(request, EINVAL);
     
    537549        TRANSFER_END(request, ENOTSUP);
    538550}
    539 /*----------------------------------------------------------------------------*/
     551
    540552/**
    541553 * process feature-enabling request on hub
     
    554566                return EINVAL;
    555567
    556         switch (feature)
    557         {
    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;
     568        switch (feature) {
     569        case USB_HUB_FEATURE_PORT_POWER:   /*8*/
     570                {
     571                        const uint32_t rhda =
     572                            OHCI_RD(instance->registers->rh_desc_a);
     573                        /* No power switching */
     574                        if (rhda & RHDA_NPS_FLAG)
     575                                return EOK;
     576                        /* Ganged power switching, one port powers all */
     577                        if (!(rhda & RHDA_PSM_FLAG)) {
     578                                OHCI_WR(instance->registers->rh_status,
     579                                    RHS_SET_GLOBAL_POWER);
     580                                return EOK;
     581                        }
    566582                }
    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);
     583                        /* Fall through */
     584        case USB_HUB_FEATURE_PORT_ENABLE:  /*1*/
     585        case USB_HUB_FEATURE_PORT_SUSPEND: /*2*/
     586        case USB_HUB_FEATURE_PORT_RESET:   /*4*/
     587                usb_log_debug2("Setting port POWER, ENABLE, SUSPEND or RESET "
     588                    "on port %"PRIu16".\n", port);
     589                OHCI_WR(instance->registers->rh_port_status[port - 1],
     590                    1 << feature);
    573591                return EOK;
    574592        default:
     
    576594        }
    577595}
    578 /*----------------------------------------------------------------------------*/
     596
    579597/**
    580598 * Process feature clear request.
     
    596614        switch (feature)
    597615        {
    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;
     616        case USB_HUB_FEATURE_PORT_POWER:          /*8*/
     617                {
     618                        const uint32_t rhda =
     619                            OHCI_RD(instance->registers->rh_desc_a);
     620                        /* No power switching */
     621                        if (rhda & RHDA_NPS_FLAG)
     622                                return ENOTSUP;
     623                        /* Ganged power switching, one port powers all */
     624                        if (!(rhda & RHDA_PSM_FLAG)) {
     625                                OHCI_WR(instance->registers->rh_status,
     626                                    RHS_CLEAR_GLOBAL_POWER);
     627                                return EOK;
     628                        }
     629                        OHCI_WR(instance->registers->rh_port_status[port - 1],
     630                            RHPS_CLEAR_PORT_POWER);
    605631                        return EOK;
    606632                }
    607                 instance->registers->rh_port_status[port - 1] =
    608                         RHPS_CLEAR_PORT_POWER;
     633
     634        case USB_HUB_FEATURE_PORT_ENABLE:         /*1*/
     635                OHCI_WR(instance->registers->rh_port_status[port - 1],
     636                    RHPS_CLEAR_PORT_ENABLE);
    609637                return EOK;
    610638
    611         case USB_HUB_FEATURE_PORT_ENABLE:         //1
    612                 instance->registers->rh_port_status[port - 1] =
    613                         RHPS_CLEAR_PORT_ENABLE;
     639        case USB_HUB_FEATURE_PORT_SUSPEND:        /*2*/
     640                OHCI_WR(instance->registers->rh_port_status[port - 1],
     641                    RHPS_CLEAR_PORT_SUSPEND);
    614642                return EOK;
    615643
    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);
     644        case USB_HUB_FEATURE_C_PORT_CONNECTION:   /*16*/
     645        case USB_HUB_FEATURE_C_PORT_ENABLE:       /*17*/
     646        case USB_HUB_FEATURE_C_PORT_SUSPEND:      /*18*/
     647        case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: /*19*/
     648        case USB_HUB_FEATURE_C_PORT_RESET:        /*20*/
     649                usb_log_debug2("Clearing port C_CONNECTION, C_ENABLE, "
     650                    "C_SUSPEND, C_OC or C_RESET on port %"PRIu16".\n", port);
     651                /* Bit offsets correspond to the feature number */
     652                OHCI_WR(instance->registers->rh_port_status[port - 1],
     653                    1 << feature);
    629654                return EOK;
    630655
     
    633658        }
    634659}
    635 /*----------------------------------------------------------------------------*/
     660
    636661/**
    637662 * process one of requests that do not request nor carry additional data
     
    654679        case USB_HUB_REQ_TYPE_SET_PORT_FEATURE:
    655680                usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    656                 int ret = set_feature_port(instance,
     681                const int ret = set_feature_port(instance,
    657682                    setup_request->value, setup_request->index);
    658683                TRANSFER_END(request, ret);
     
    671696        }
    672697}
    673 /*----------------------------------------------------------------------------*/
     698
    674699/**
    675700 * process one of requests that do not request nor carry additional data
     
    693718        case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE:
    694719                usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n");
    695                 int ret = clear_feature_port(instance,
     720                const int ret = clear_feature_port(instance,
    696721                    setup_request->value, setup_request->index);
    697722                TRANSFER_END(request, ret);
     
    706731                 * as root hubs do not support local power status feature.
    707732                 * (OHCI pg. 127) */
    708                 if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
    709                         instance->registers->rh_status = RHS_OCIC_FLAG;
     733                if (uint16_usb2host(setup_request->value)
     734                    == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
     735                        OHCI_WR(instance->registers->rh_status, RHS_OCIC_FLAG);
    710736                        TRANSFER_END(request, EOK);
    711737                }
     
    717743        }
    718744}
    719 /*----------------------------------------------------------------------------*/
     745
    720746/**
    721747 * Process hub control request.
     
    771797                if (request->buffer_size == 0)
    772798                        TRANSFER_END(request, EOVERFLOW);
    773                 uint8_t config = 1;
     799                const uint8_t config = 1;
    774800                TRANSFER_END_DATA(request, &config, sizeof(config));
    775801
     
    790816                        TRANSFER_END(request, EINVAL);
    791817
    792                 instance->address = setup_request->value;
     818                instance->address = uint16_usb2host(setup_request->value);
    793819                TRANSFER_END(request, EOK);
    794820
    795821        case USB_DEVREQ_SET_CONFIGURATION:
    796822                usb_log_debug("USB_DEVREQ_SET_CONFIGURATION: %u\n",
    797                     setup_request->value);
     823                    uint16_usb2host(setup_request->value));
    798824                /* We have only one configuration, it's number is 1 */
    799825                if (uint16_usb2host(setup_request->value) != 1)
Note: See TracChangeset for help on using the changeset viewer.