Ignore:
File:
1 edited

Legend:

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

    rd3dd96e r99e8fb7b  
    4343#include <usb/debug.h>
    4444#include <device/hw_res_parsed.h>
    45 #include <device/pci.h>
     45#include <pci_dev_iface.h>
    4646
    4747#include "res.h"
    48 #include "ehci_regs.h"
     48
     49#define HCC_PARAMS_OFFSET 0x8
     50#define HCC_PARAMS_EECP_MASK 0xff
     51#define HCC_PARAMS_EECP_OFFSET 8
     52
     53#define CMD_OFFSET 0x0
     54#define STS_OFFSET 0x4
     55#define INT_OFFSET 0x8
     56#define CFG_OFFSET 0x40
     57
     58#define USBCMD_RUN 1
     59#define USBSTS_HALTED (1 << 12)
    4960
    5061#define USBLEGSUP_OFFSET 0
     
    5566#define DEFAULT_WAIT 1000
    5667#define WAIT_STEP 10
     68
     69
     70/** Get address of registers and IRQ for given device.
     71 *
     72 * @param[in] dev Device asking for the addresses.
     73 * @param[out] mem_regs_p Pointer to the register range.
     74 * @param[out] irq_no IRQ assigned to the device.
     75 * @return Error code.
     76 */
     77int get_my_registers(ddf_dev_t *dev,
     78    addr_range_t *mem_regs_p, int *irq_no)
     79{
     80        assert(dev);
     81       
     82        async_sess_t *parent_sess = devman_parent_device_connect(
     83            EXCHANGE_SERIALIZE, ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
     84        if (!parent_sess)
     85                return ENOMEM;
     86       
     87        hw_res_list_parsed_t hw_res;
     88        hw_res_list_parsed_init(&hw_res);
     89        const int ret = hw_res_get_list_parsed(parent_sess, &hw_res, 0);
     90        async_hangup(parent_sess);
     91        if (ret != EOK) {
     92                return ret;
     93        }
     94
     95        if (hw_res.irqs.count != 1 || hw_res.mem_ranges.count != 1) {
     96                hw_res_list_parsed_clean(&hw_res);
     97                return ENOENT;
     98        }
     99
     100        if (mem_regs_p)
     101                *mem_regs_p = hw_res.mem_ranges.ranges[0];
     102        if (irq_no)
     103                *irq_no = hw_res.irqs.irqs[0];
     104
     105        hw_res_list_parsed_clean(&hw_res);
     106        return EOK;
     107}
     108
     109/** Calls the PCI driver with a request to enable interrupts
     110 *
     111 * @param[in] device Device asking for interrupts
     112 * @return Error code.
     113 */
     114int enable_interrupts(ddf_dev_t *device)
     115{
     116        async_sess_t *parent_sess = devman_parent_device_connect(
     117            EXCHANGE_SERIALIZE, ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
     118        if (!parent_sess)
     119                return ENOMEM;
     120       
     121        const bool enabled = hw_res_enable_interrupt(parent_sess);
     122        async_hangup(parent_sess);
     123       
     124        return enabled ? EOK : EIO;
     125}
    57126
    58127/** Implements BIOS hands-off routine as described in EHCI spec
     
    73142                return ENOMEM;
    74143
    75 #define CHECK_RET_HANGUP_RETURN(ret, message...) \
    76         if (ret != EOK) { \
    77                 usb_log_error(message); \
    78                 async_hangup(parent_sess); \
    79                 return ret; \
    80         } else (void)0
    81 
    82144        /* Read the first EEC. i.e. Legacy Support register */
    83145        uint32_t usblegsup;
    84         int ret = pci_config_space_read_32(parent_sess,
     146        int rc = pci_config_space_read_32(parent_sess,
    85147            eecp + USBLEGSUP_OFFSET, &usblegsup);
    86         CHECK_RET_HANGUP_RETURN(ret,
    87             "Failed to read USBLEGSUP: %s.\n", str_error(ret));
     148        if (rc != EOK) {
     149                usb_log_error("Failed to read USBLEGSUP: %s.\n",
     150                    str_error(rc));
     151                goto error;
     152        }
     153
    88154        usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
    89155
     
    91157         * byte. (OS Control semaphore)*/
    92158        usb_log_debug("Requesting OS control.\n");
    93         ret = pci_config_space_write_8(parent_sess,
     159        rc = pci_config_space_write_8(parent_sess,
    94160            eecp + USBLEGSUP_OFFSET + 3, 1);
    95         CHECK_RET_HANGUP_RETURN(ret, "Failed to request OS EHCI control: %s.\n",
    96             str_error(ret));
     161        if (rc != EOK) {
     162                usb_log_error("Failed to request OS EHCI control: %s.\n",
     163                    str_error(rc));
     164                goto error;
     165        }
    97166
    98167        size_t wait = 0;
    99168        /* Wait for BIOS to release control. */
    100         ret = pci_config_space_read_32(
     169        rc = pci_config_space_read_32(
    101170            parent_sess, eecp + USBLEGSUP_OFFSET, &usblegsup);
     171        if (rc != EOK) {
     172                usb_log_error("Failed reading PCI config space: %s.\n",
     173                    str_error(rc));
     174                goto error;
     175        }
     176
    102177        while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
    103178                async_usleep(WAIT_STEP);
    104                 ret = pci_config_space_read_32(parent_sess,
     179                rc = pci_config_space_read_32(parent_sess,
    105180                    eecp + USBLEGSUP_OFFSET, &usblegsup);
     181                if (rc != EOK) {
     182                        usb_log_error("Failed reading PCI config space: %s.\n",
     183                            str_error(rc));
     184                        goto error;
     185                }
    106186                wait += WAIT_STEP;
    107187        }
     
    116196        usb_log_warning( "BIOS failed to release control after "
    117197            "%zu usecs, force it.\n", wait);
    118         ret = pci_config_space_write_32(parent_sess,
     198        rc = pci_config_space_write_32(parent_sess,
    119199            eecp + USBLEGSUP_OFFSET, USBLEGSUP_OS_CONTROL);
    120         CHECK_RET_HANGUP_RETURN(ret, "Failed to force OS control: "
    121             "%s.\n", str_error(ret));
     200        if (rc != EOK) {
     201                usb_log_error("Failed to force OS control: "
     202                    "%s.\n", str_error(rc));
     203                goto error;
     204        }
     205
    122206        /*
    123207         * Check capability type here, value of 01h identifies the capability
     
    129213                /* Read the second EEC Legacy Support and Control register */
    130214                uint32_t usblegctlsts;
    131                 ret = pci_config_space_read_32(parent_sess,
     215                rc = pci_config_space_read_32(parent_sess,
    132216                    eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    133                 CHECK_RET_HANGUP_RETURN(ret, "Failed to get USBLEGCTLSTS: %s.\n",
    134                     str_error(ret));
     217                if (rc != EOK) {
     218                        usb_log_error("Failed to get USBLEGCTLSTS: %s.\n",
     219                            str_error(rc));
     220                        goto error;
     221                }
     222
    135223                usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n", usblegctlsts);
    136224                /*
     
    139227                 * interfering. NOTE: Three upper bits are WC
    140228                 */
    141                 ret = pci_config_space_write_32(parent_sess,
     229                rc = pci_config_space_write_32(parent_sess,
    142230                    eecp + USBLEGCTLSTS_OFFSET, 0xe0000000);
    143                 CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) zero USBLEGCTLSTS.\n", ret);
     231                if (rc != EOK) {
     232                        usb_log_error("Failed(%d) zero USBLEGCTLSTS.\n", rc);
     233                        goto error;
     234                }
     235
    144236                udelay(10);
    145                 ret = pci_config_space_read_32(parent_sess,
     237                rc = pci_config_space_read_32(parent_sess,
    146238                    eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    147                 CHECK_RET_HANGUP_RETURN(ret, "Failed to get USBLEGCTLSTS 2: %s.\n",
    148                     str_error(ret));
     239                if (rc != EOK) {
     240                        usb_log_error("Failed to get USBLEGCTLSTS 2: %s.\n",
     241                            str_error(rc));
     242                        goto error;
     243                }
     244
    149245                usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n",
    150246                    usblegctlsts);
     
    152248
    153249        /* Read again Legacy Support register */
    154         ret = pci_config_space_read_32(parent_sess,
     250        rc = pci_config_space_read_32(parent_sess,
    155251            eecp + USBLEGSUP_OFFSET, &usblegsup);
    156         CHECK_RET_HANGUP_RETURN(ret, "Failed to read USBLEGSUP: %s.\n",
    157             str_error(ret));
     252        if (rc != EOK) {
     253                usb_log_error("Failed to read USBLEGSUP: %s.\n",
     254                    str_error(rc));
     255                goto error;
     256        }
     257
    158258        usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
    159259        async_hangup(parent_sess);
    160260        return EOK;
    161 #undef CHECK_RET_HANGUP_RETURN
     261error:
     262        async_hangup(parent_sess);
     263        return rc;
    162264}
    163265
     
    169271        /* Map EHCI registers */
    170272        void *regs = NULL;
    171         int ret = pio_enable_range(reg_range, &regs);
    172         if (ret != EOK) {
     273        int rc = pio_enable_range(reg_range, &regs);
     274        if (rc != EOK) {
    173275                usb_log_error("Failed to map registers %p: %s.\n",
    174                     RNGABSPTR(*reg_range), str_error(ret));
    175                 return ret;
     276                    RNGABSPTR(*reg_range), str_error(rc));
     277                return rc;
    176278        }
    177279
    178280        usb_log_debug2("Registers mapped at: %p.\n", regs);
    179281
    180         ehci_caps_regs_t *ehci_caps = regs;
    181 
    182         const uint32_t hcc_params = EHCI_RD(ehci_caps->hccparams);
     282        const uint32_t hcc_params =
     283            *(uint32_t*)(regs + HCC_PARAMS_OFFSET);
    183284        usb_log_debug("Value of hcc params register: %x.\n", hcc_params);
    184285
     
    186287         * position of EEC registers (points to PCI config space) */
    187288        const uint32_t eecp =
    188             (hcc_params >> EHCI_CAPS_HCC_EECP_SHIFT) & EHCI_CAPS_HCC_EECP_MASK;
     289            (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;
    189290        usb_log_debug("Value of EECP: %x.\n", eecp);
    190291
    191         ret = disable_extended_caps(device, eecp);
    192         if (ret != EOK) {
     292        rc = disable_extended_caps(device, eecp);
     293        if (rc != EOK) {
    193294                usb_log_error("Failed to disable extended capabilities: %s.\n",
    194                     str_error(ret));
    195                 return ret;
    196         }
    197 
     295                    str_error(rc));
     296                return rc;
     297        }
    198298
    199299        /*
     
    202302
    203303        /* Get size of capability registers in memory space. */
    204         const unsigned operation_offset = EHCI_RD8(ehci_caps->caplength);
     304        const unsigned operation_offset = *(uint8_t*)regs;
    205305        usb_log_debug("USBCMD offset: %d.\n", operation_offset);
    206306
    207         ehci_regs_t *ehci_regs = regs + operation_offset;
    208 
    209         usb_log_debug("USBCMD value: %x.\n", EHCI_RD(ehci_regs->usbcmd));
    210         if (EHCI_RD(ehci_regs->usbcmd) & USB_CMD_RUN_FLAG) {
    211                 EHCI_WR(ehci_regs->usbintr, 0); /* disable all interrupts */
    212                 EHCI_WR(ehci_regs->usbsts, 0x3f); /* ack all interrupts */
    213                 EHCI_WR(ehci_regs->configflag, 0); /* release RH ports */
    214                 EHCI_WR(ehci_regs->usbcmd, 0);
     307        /* Zero USBCMD register. */
     308        volatile uint32_t *usbcmd =
     309            (uint32_t*)((uint8_t*)regs + operation_offset + CMD_OFFSET);
     310        volatile uint32_t *usbsts =
     311            (uint32_t*)((uint8_t*)regs + operation_offset + STS_OFFSET);
     312        volatile uint32_t *usbconf =
     313            (uint32_t*)((uint8_t*)regs + operation_offset + CFG_OFFSET);
     314        volatile uint32_t *usbint =
     315            (uint32_t*)((uint8_t*)regs + operation_offset + INT_OFFSET);
     316        usb_log_debug("USBCMD value: %x.\n", *usbcmd);
     317        if (*usbcmd & USBCMD_RUN) {
     318                *usbsts = 0x3f; /* ack all interrupts */
     319                *usbint = 0; /* disable all interrupts */
     320                *usbconf = 0; /* release control of RH ports */
     321
     322                *usbcmd = 0;
    215323                /* Wait until hc is halted */
    216                 while ((EHCI_RD(ehci_regs->usbsts) & USB_STS_HC_HALTED_FLAG) == 0);
     324                while ((*usbsts & USBSTS_HALTED) == 0);
    217325                usb_log_info("EHCI turned off.\n");
    218326        } else {
     
    224332            "\t USBINT(%p): %x(0x0 = no interrupts).\n"
    225333            "\t CONFIG(%p): %x(0x0 = ports controlled by companion hc).\n",
    226             &ehci_regs->usbcmd, EHCI_RD(ehci_regs->usbcmd),
    227             &ehci_regs->usbsts, EHCI_RD(ehci_regs->usbsts),
    228             &ehci_regs->usbintr, EHCI_RD(ehci_regs->usbintr),
    229             &ehci_regs->configflag, EHCI_RD(ehci_regs->configflag));
    230 
    231         return ret;
     334            usbcmd, *usbcmd, usbsts, *usbsts, usbint, *usbint, usbconf,*usbconf);
     335
     336        return rc;
    232337}
    233338
Note: See TracChangeset for help on using the changeset viewer.