Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset dbbba51c in mainline


Ignore:
Timestamp:
2012-03-15T22:46:18Z (10 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master
Children:
14f8fd4
Parents:
68e48db
Message:

ehci: Move handling of extended capabilities to separate function.

File:
1 edited

Legend:

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

    r68e48db rdbbba51c  
    128128}
    129129/*----------------------------------------------------------------------------*/
    130 /** Implements BIOS handoff routine as decribed in EHCI spec
    131  *
    132  * @param[in] device Device asking for interrupts
     130/** Implements BIOS hands-off routine as described in EHCI spec
     131 *
     132 * @param device EHCI device
     133 * @param eecp Value of EHCI Extended Capabilities pointer.
    133134 * @return Error code.
    134135 */
    135 int disable_legacy(const ddf_dev_t *device, uintptr_t reg_base, size_t reg_size)
     136static int disable_extended_caps(const ddf_dev_t *device, unsigned eecp)
    136137{
    137         assert(device);
     138        /* nothing to do */
     139        if (eecp == 0)
     140                return EOK;
     141
    138142        async_sess_t *parent_sess = devman_parent_device_connect(
    139143            EXCHANGE_SERIALIZE, device->handle, IPC_FLAG_BLOCKING);
     
    141145                return ENOMEM;
    142146
    143 #define CHECK_RET_RETURN(ret, message...) \
     147#define CHECK_RET_HANGUP_RETURN(ret, message...) \
    144148        if (ret != EOK) { \
    145149                usb_log_error(message); \
     
    148152        } else (void)0
    149153
     154        /* Read the first EEC. i.e. Legacy Support register */
     155        uint32_t usblegsup;
     156        int ret = pci_config_space_read_32(parent_sess,
     157            eecp + USBLEGSUP_OFFSET, &usblegsup);
     158        CHECK_RET_HANGUP_RETURN(ret,
     159            "Failed to read USBLEGSUP: %s.\n", str_error(ret));
     160        usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
     161
     162        /* Request control from firmware/BIOS by writing 1 to highest
     163         * byte. (OS Control semaphore)*/
     164        usb_log_debug("Requesting OS control.\n");
     165        ret = pci_config_space_write_8(parent_sess,
     166            eecp + USBLEGSUP_OFFSET + 3, 1);
     167        CHECK_RET_HANGUP_RETURN(ret, "Failed to request OS EHCI control: %s.\n",
     168            str_error(ret));
     169
     170        size_t wait = 0;
     171        /* Wait for BIOS to release control. */
     172        ret = pci_config_space_read_32(
     173            parent_sess, eecp + USBLEGSUP_OFFSET, &usblegsup);
     174        while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
     175                async_usleep(WAIT_STEP);
     176                ret = pci_config_space_read_32(parent_sess,
     177                    eecp + USBLEGSUP_OFFSET, &usblegsup);
     178                wait += WAIT_STEP;
     179        }
     180
     181        if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) {
     182                usb_log_info("BIOS released control after %zu usec.\n", wait);
     183                async_hangup(parent_sess);
     184                return EOK;
     185        }
     186
     187        /* BIOS failed to hand over control, this should not happen. */
     188        usb_log_warning( "BIOS failed to release control after "
     189            "%zu usecs, force it.\n", wait);
     190        ret = pci_config_space_write_32(parent_sess,
     191            eecp + USBLEGSUP_OFFSET, USBLEGSUP_OS_CONTROL);
     192        CHECK_RET_HANGUP_RETURN(ret, "Failed to force OS control: "
     193            "%s.\n", str_error(ret));
     194        /*
     195         * Check capability type here, value of 01h identifies the capability
     196         * as Legacy Support. This extended capability requires one additional
     197         * 32-bit register for control/status information and this register is
     198         * located at offset EECP+04h
     199         */
     200        if ((usblegsup & 0xff) == 1) {
     201                /* Read the second EEC Legacy Support and Control register */
     202                uint32_t usblegctlsts;
     203                ret = pci_config_space_read_32(parent_sess,
     204                    eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
     205                CHECK_RET_HANGUP_RETURN(ret, "Failed to get USBLEGCTLSTS: %s.\n",
     206                    str_error(ret));
     207                usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n", usblegctlsts);
     208                /*
     209                 * Zero SMI enables in legacy control register.
     210                 * It should prevent pre-OS code from
     211                 * interfering. NOTE: Three upper bits are WC
     212                 */
     213                ret = pci_config_space_write_32(parent_sess,
     214                    eecp + USBLEGCTLSTS_OFFSET, 0xe0000000);
     215                CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) zero USBLEGCTLSTS.\n", ret);
     216                udelay(10);
     217                ret = pci_config_space_read_32(parent_sess,
     218                    eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
     219                CHECK_RET_HANGUP_RETURN(ret, "Failed to get USBLEGCTLSTS 2: %s.\n",
     220                    str_error(ret));
     221                usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n",
     222                    usblegctlsts);
     223        }
     224
     225        /* Read again Legacy Support register */
     226        ret = pci_config_space_read_32(parent_sess,
     227            eecp + USBLEGSUP_OFFSET, &usblegsup);
     228        CHECK_RET_HANGUP_RETURN(ret, "Failed to read USBLEGSUP: %s.\n",
     229            str_error(ret));
     230        usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
     231        async_hangup(parent_sess);
     232        return EOK;
     233#undef CHECK_RET_HANGUP_RETURN
     234}
     235
     236int disable_legacy(const ddf_dev_t *device, uintptr_t reg_base, size_t reg_size)
     237{
     238        assert(device);
     239
     240#define CHECK_RET_RETURN(ret, message...) \
     241        if (ret != EOK) { \
     242                usb_log_error(message); \
     243                return ret; \
     244        } else (void)0
     245
    150246        /* Map EHCI registers */
    151247        void *regs = NULL;
     
    164260        usb_log_debug("Value of EECP: %x.\n", eecp);
    165261
    166         /* Read the first EEC. i.e. Legacy Support register */
    167         uint32_t usblegsup;
    168         ret = pci_config_space_read_32(parent_sess,
    169             eecp + USBLEGSUP_OFFSET, &usblegsup);
    170         CHECK_RET_RETURN(ret, "Failed to read USBLEGSUP: %s.\n", str_error(ret));
    171         usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
    172 
    173         /* Request control from firmware/BIOS, by writing 1 to highest byte.
    174          * (OS Control semaphore)*/
    175         usb_log_debug("Requesting OS control.\n");
    176         ret = pci_config_space_write_8(parent_sess,
    177             eecp + USBLEGSUP_OFFSET + 3, 1);
    178         CHECK_RET_RETURN(ret, "Failed to request OS EHCI control: %s.\n",
     262        ret = disable_extended_caps(device, eecp);
     263        CHECK_RET_RETURN(ret, "Failed to disable extended capabilities: %s.\n",
    179264            str_error(ret));
    180265
    181         size_t wait = 0;
    182         /* Wait for BIOS to release control. */
    183         ret = pci_config_space_read_32(parent_sess,
    184             eecp + USBLEGSUP_OFFSET, &usblegsup);
    185         while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
    186                 async_usleep(WAIT_STEP);
    187                 ret = pci_config_space_read_32(parent_sess,
    188                     eecp + USBLEGSUP_OFFSET, &usblegsup);
    189                 wait += WAIT_STEP;
    190         }
    191 
    192 
    193         if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) {
    194                 usb_log_info("BIOS released control after %zu usec.\n", wait);
    195         } else {
    196                 /* BIOS failed to hand over control, this should not happen. */
    197                 usb_log_warning( "BIOS failed to release control after "
    198                     "%zu usecs, force it.\n", wait);
    199                 ret = pci_config_space_write_32(parent_sess,
    200                     eecp + USBLEGSUP_OFFSET, USBLEGSUP_OS_CONTROL);
    201                 CHECK_RET_RETURN(ret, "Failed to force OS control: %s.\n",
    202                     str_error(ret));
    203                 /* Check capability type here, A value of 01h
    204                  * identifies the capability as Legacy Support.
    205                  * This extended capability requires one
    206                  * additional 32-bit register for control/status information,
    207                  * and this register is located at offset EECP+04h
    208                  * */
    209                 if ((usblegsup & 0xff) == 1) {
    210                         /* Read the second EEC
    211                          * Legacy Support and Control register */
    212                         uint32_t usblegctlsts;
    213                         ret = pci_config_space_read_32(parent_sess,
    214                             eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    215                         CHECK_RET_RETURN(ret,
    216                             "Failed to get USBLEGCTLSTS: %s.\n", str_error(ret));
    217                         usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n",
    218                             usblegctlsts);
    219                         /* Zero SMI enables in legacy control register.
    220                          * It should prevent pre-OS code from interfering.
    221                          * Three upper bits are WC */
    222                         ret = pci_config_space_write_32(parent_sess,
    223                             eecp + USBLEGCTLSTS_OFFSET, 0xe0000000);
    224                         CHECK_RET_RETURN(ret,
    225                             "Failed(%d) zero USBLEGCTLSTS.\n", ret);
    226                         udelay(10);
    227                         ret = pci_config_space_read_32(parent_sess,
    228                             eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    229                         CHECK_RET_RETURN(ret,
    230                             "Failed to get USBLEGCTLSTS 2: %s.\n",
    231                             str_error(ret));
    232                         usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n",
    233                             usblegctlsts);
    234                 }
    235         }
    236 
    237 
    238         /* Read again Legacy Support register */
    239         ret = pci_config_space_read_32(parent_sess,
    240             eecp + USBLEGSUP_OFFSET, &usblegsup);
    241         CHECK_RET_RETURN(ret, "Failed to read USBLEGSUP: %s.\n", str_error(ret));
    242         usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
    243 
    244         async_hangup(parent_sess);
    245266#undef CHECK_RET_RETURN
    246267
Note: See TracChangeset for help on using the changeset viewer.