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

Changeset 6e5369b in mainline


Ignore:
Timestamp:
2012-04-08T05:17:27Z (10 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master
Children:
5b7ba8d
Parents:
6c76e75
Message:

ehci: Move handling of extended capabilities to a separate function.

File:
1 edited

Legend:

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

    r6c76e75 r6e5369b  
    4646
    4747#include "res.h"
    48 
    49 #define PAGE_SIZE_MASK 0xfffff000
    5048
    5149#define HCC_PARAMS_OFFSET 0x8
     
    130128}
    131129/*----------------------------------------------------------------------------*/
    132 /** Implements BIOS handoff routine as decribed in EHCI spec
    133  *
    134  * @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.
    135134 * @return Error code.
    136135 */
    137 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)
    138137{
    139         assert(device);
     138        /* nothing to do */
     139        if (eecp == 0)
     140                return EOK;
     141
    140142        async_sess_t *parent_sess = devman_parent_device_connect(
    141143            EXCHANGE_SERIALIZE, device->handle, IPC_FLAG_BLOCKING);
     
    143145                return ENOMEM;
    144146
    145 #define CHECK_RET_RETURN(ret, message...) \
     147#define CHECK_RET_HANGUP_RETURN(ret, message...) \
    146148        if (ret != EOK) { \
    147149                usb_log_error(message); \
     
    150152        } else (void)0
    151153
     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
    152246        /* Map EHCI registers */
    153247        void *regs = NULL;
     
    166260        usb_log_debug("Value of EECP: %x.\n", eecp);
    167261
    168         /* Read the first EEC. i.e. Legacy Support register */
    169         uint32_t usblegsup;
    170         ret = pci_config_space_read_32(parent_sess,
    171             eecp + USBLEGSUP_OFFSET, &usblegsup);
    172         CHECK_RET_RETURN(ret, "Failed to read USBLEGSUP: %s.\n", str_error(ret));
    173         usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
    174 
    175         /* Request control from firmware/BIOS, by writing 1 to highest byte.
    176          * (OS Control semaphore)*/
    177         usb_log_debug("Requesting OS control.\n");
    178         ret = pci_config_space_write_8(parent_sess,
    179             eecp + USBLEGSUP_OFFSET + 3, 1);
    180         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",
    181264            str_error(ret));
    182265
    183         size_t wait = 0;
    184         /* Wait for BIOS to release control. */
    185         ret = pci_config_space_read_32(parent_sess,
    186             eecp + USBLEGSUP_OFFSET, &usblegsup);
    187         while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
    188                 async_usleep(WAIT_STEP);
    189                 ret = pci_config_space_read_32(parent_sess,
    190                     eecp + USBLEGSUP_OFFSET, &usblegsup);
    191                 wait += WAIT_STEP;
    192         }
    193 
    194 
    195         if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) {
    196                 usb_log_info("BIOS released control after %zu usec.\n", wait);
    197         } else {
    198                 /* BIOS failed to hand over control, this should not happen. */
    199                 usb_log_warning( "BIOS failed to release control after "
    200                     "%zu usecs, force it.\n", wait);
    201                 ret = pci_config_space_write_32(parent_sess,
    202                     eecp + USBLEGSUP_OFFSET, USBLEGSUP_OS_CONTROL);
    203                 CHECK_RET_RETURN(ret, "Failed to force OS control: %s.\n",
    204                     str_error(ret));
    205                 /* Check capability type here, A value of 01h
    206                  * identifies the capability as Legacy Support.
    207                  * This extended capability requires one
    208                  * additional 32-bit register for control/status information,
    209                  * and this register is located at offset EECP+04h
    210                  * */
    211                 if ((usblegsup & 0xff) == 1) {
    212                         /* Read the second EEC
    213                          * Legacy Support and Control register */
    214                         uint32_t usblegctlsts;
    215                         ret = pci_config_space_read_32(parent_sess,
    216                             eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    217                         CHECK_RET_RETURN(ret,
    218                             "Failed to get USBLEGCTLSTS: %s.\n", str_error(ret));
    219                         usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n",
    220                             usblegctlsts);
    221                         /* Zero SMI enables in legacy control register.
    222                          * It should prevent pre-OS code from interfering.
    223                          * Three upper bits are WC */
    224                         ret = pci_config_space_write_32(parent_sess,
    225                             eecp + USBLEGCTLSTS_OFFSET, 0xe0000000);
    226                         CHECK_RET_RETURN(ret,
    227                             "Failed(%d) zero USBLEGCTLSTS.\n", ret);
    228                         udelay(10);
    229                         ret = pci_config_space_read_32(parent_sess,
    230                             eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    231                         CHECK_RET_RETURN(ret,
    232                             "Failed to get USBLEGCTLSTS 2: %s.\n",
    233                             str_error(ret));
    234                         usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n",
    235                             usblegctlsts);
    236                 }
    237         }
    238 
    239 
    240         /* Read again Legacy Support register */
    241         ret = pci_config_space_read_32(parent_sess,
    242             eecp + USBLEGSUP_OFFSET, &usblegsup);
    243         CHECK_RET_RETURN(ret, "Failed to read USBLEGSUP: %s.\n", str_error(ret));
    244         usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
    245 
    246         async_hangup(parent_sess);
    247266#undef CHECK_RET_RETURN
    248267
Note: See TracChangeset for help on using the changeset viewer.