Changeset b4b534ac in mainline for uspace/drv/bus/usb/ehci


Ignore:
Timestamp:
2016-07-22T08:24:47Z (10 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f76d2c2
Parents:
5b18137 (diff), 8351f9a4 (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:

Merge from lp:~jan.vesely/helenos/usb

Location:
uspace/drv/bus/usb/ehci
Files:
15 added
4 edited
5 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ehci/Makefile

    r5b18137 rb4b534ac  
    3131LIBS = \
    3232        $(LIBUSBHOST_PREFIX)/libusbhost.a \
     33        $(LIBUSBVIRT_PREFIX)/libusbvirt.a \
    3334        $(LIBUSB_PREFIX)/libusb.a \
    3435        $(LIBDRV_PREFIX)/libdrv.a
     
    3637EXTRA_CFLAGS += \
    3738        -I$(LIBUSB_PREFIX)/include \
     39        -I$(LIBUSBDEV_PREFIX)/include \
    3840        -I$(LIBUSBHOST_PREFIX)/include \
     41        -I$(LIBUSBVIRT_PREFIX)/include \
    3942        -I$(LIBDRV_PREFIX)/include
    4043
     
    4245
    4346SOURCES = \
     47        ehci_batch.c \
     48        ehci_endpoint.c \
     49        ehci_rh.c \
     50        endpoint_list.c \
     51        hc.c \
     52        hw_struct/queue_head.c \
     53        hw_struct/transfer_descriptor.c \
    4454        main.c \
    4555        res.c
  • uspace/drv/bus/usb/ehci/ehci_endpoint.h

    r5b18137 rb4b534ac  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcirh
     28/** @addtogroup drvusbehci
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief EHCI driver
    3333 */
    34 #ifndef DRV_UHCI_ROOT_HUB_H
    35 #define DRV_UHCI_ROOT_HUB_H
     34#ifndef DRV_EHCI_HCD_ENDPOINT_H
     35#define DRV_EHCI_HCD_ENDPOINT_H
    3636
    37 #include <ddf/driver.h>
    38 #include <device/hw_res_parsed.h>
     37#include <assert.h>
     38#include <adt/list.h>
     39#include <usb/host/endpoint.h>
     40#include <usb/host/hcd.h>
    3941
    40 #include "port.h"
     42#include "hw_struct/queue_head.h"
     43#include "hw_struct/transfer_descriptor.h"
    4144
    42 #define UHCI_ROOT_HUB_PORT_COUNT 2
    43 #define ROOT_HUB_WAIT_USEC 250000 /* 250 miliseconds */
     45/** Connector structure linking ED to to prepared TD. */
     46typedef struct ehci_endpoint {
     47        /** EHCI endpoint descriptor */
     48        qh_t *qh;
     49        /** Linked list used by driver software */
     50        link_t link;
     51} ehci_endpoint_t;
    4452
    45 /** UHCI root hub drvier structure */
    46 typedef struct root_hub {
    47         /** Ports provided by the hub */
    48         uhci_port_t ports[UHCI_ROOT_HUB_PORT_COUNT];
    49 } uhci_root_hub_t;
     53int ehci_endpoint_init(hcd_t *hcd, endpoint_t *ep);
     54void ehci_endpoint_fini(hcd_t *hcd, endpoint_t *ep);
    5055
    51 int uhci_root_hub_init(uhci_root_hub_t *instance, addr_range_t *regs,
    52     ddf_dev_t *rh);
     56/** Get and convert assigned ehci_endpoint_t structure
     57 * @param[in] ep USBD endpoint structure.
     58 * @return Pointer to assigned hcd endpoint structure
     59 */
     60static inline ehci_endpoint_t * ehci_endpoint_get(const endpoint_t *ep)
     61{
     62        assert(ep);
     63        return ep->hc_data.data;
     64}
    5365
    54 void uhci_root_hub_fini(uhci_root_hub_t *instance);
     66static inline ehci_endpoint_t * ehci_endpoint_list_instance(link_t *l)
     67{
     68        return list_get_instance(l, ehci_endpoint_t, link);
     69}
     70
    5571#endif
    5672/**
    5773 * @}
    5874 */
     75
  • uspace/drv/bus/usb/ehci/ehci_rh.h

    r5b18137 rb4b534ac  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2013 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhci
     28/** @addtogroup drvusbehci
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief EHCI driver
    3333 */
     34#ifndef DRV_EHCI_EHCI_RH_H
     35#define DRV_EHCI_EHCI_RH_H
     36
    3437#include <assert.h>
    35 #include <errno.h>
    36 #include <str_error.h>
    37 #include <stdio.h>
    38 #include <device/hw_res_parsed.h>
     38#include <sys/types.h>
    3939
    40 #include <usb/debug.h>
     40#include <usb/usb.h>
     41#include <usb/classes/hub.h>
     42#include <usb/host/usb_transfer_batch.h>
     43#include <usbvirt/virthub_base.h>
    4144
    42 #include "root_hub.h"
     45#include "ehci_regs.h"
    4346
    44 /** Root hub initialization
    45  * @param[in] instance RH structure to initialize
    46  * @param[in] fun DDF function representing UHCI root hub
    47  * @param[in] reg_addr Address of root hub status and control registers.
    48  * @param[in] reg_size Size of accessible address space.
    49  * @return Error code.
     47enum {
     48        EHCI_MAX_PORTS = 15,
     49};
     50
     51typedef struct {
     52        /** Virtual hub instance */
     53        virthub_base_t base;
     54        /** EHCI device registers */
     55        ehci_regs_t *registers;
     56        /** Number of downstream ports, EHCI limits this to 15 */
     57        unsigned port_count;
     58        /** USB hub descriptor describing the EHCI root hub */
     59        struct {
     60                usb_hub_descriptor_header_t header;
     61                uint8_t rempow[STATUS_BYTES(EHCI_MAX_PORTS) * 2];
     62        } __attribute__((packed)) hub_descriptor;
     63        /** interrupt transfer waiting for an actual interrupt to occur */
     64        usb_transfer_batch_t *unfinished_interrupt_transfer;
     65        bool reset_flag[EHCI_MAX_PORTS];
     66        bool resume_flag[EHCI_MAX_PORTS];
     67} ehci_rh_t;
     68
     69int ehci_rh_init(ehci_rh_t *instance, ehci_caps_regs_t *caps, ehci_regs_t *regs,
     70    const char *name);
     71int ehci_rh_schedule(ehci_rh_t *instance, usb_transfer_batch_t *batch);
     72int ehci_rh_interrupt(ehci_rh_t *instance);
     73
     74/** Get EHCI rh address.
     75 *
     76 * @param instance UHCI rh instance.
     77 * @return USB address assigned to the hub.
     78 * Wrapper for virtual hub address
    5079 */
    51 int
    52 rh_init(rh_t *instance, ddf_fun_t *fun, addr_range_t *regs, uintptr_t reg_addr,
    53     size_t reg_size)
     80static inline usb_address_t ehci_rh_get_address(ehci_rh_t *instance)
    5481{
    5582        assert(instance);
    56         assert(fun);
    57 
    58         /* Crop the PIO window to the absolute address range of UHCI I/O. */
    59         instance->pio_window.mem.base = 0;
    60         instance->pio_window.mem.size = 0;
    61         instance->pio_window.io.base = RNGABS(*regs);
    62         instance->pio_window.io.size = RNGSZ(*regs);
    63 
    64         /* Initialize resource structure */
    65         instance->resource_list.count = 1;
    66         instance->resource_list.resources = &instance->io_regs;
    67 
    68         instance->io_regs.type = IO_RANGE;
    69         instance->io_regs.res.io_range.address = reg_addr;
    70         instance->io_regs.res.io_range.size = reg_size;
    71         instance->io_regs.res.io_range.relative = true;
    72         instance->io_regs.res.io_range.endianness = LITTLE_ENDIAN;
    73 
    74         const int ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100);
    75         if (ret != EOK) {
    76                 usb_log_error("Failed to add root hub match id: %s\n",
    77                     str_error(ret));
    78         }
    79         return ret;
     83        return virthub_base_get_address(&instance->base);
    8084}
     85#endif
    8186/**
    8287 * @}
  • uspace/drv/bus/usb/ehci/hw_struct/fstn.h

    r5b18137 rb4b534ac  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2013 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    29 /** @addtogroup drvusbuhci
     28/** @addtogroup drvusbehci
    3029 * @{
    3130 */
    3231/** @file
    33  * @brief UHCI driver main structure for both host controller and root-hub.
     32 * @brief EHCI driver
    3433 */
    35 #ifndef DRV_UHCI_UHCI_H
    36 #define DRV_UHCI_UHCI_H
    37 #include <ddf/driver.h>
     34#ifndef DRV_EHCI_HW_STRUCT_FSTN_H
     35#define DRV_EHCI_HW_STRUCT_FSTN_H
    3836
    39 int device_setup_uhci(ddf_dev_t *device);
     37#include "link_pointer.h"
     38
     39typedef struct fstn {
     40        link_pointer_t normal_path;
     41        link_pointer_t back_path;
     42} fstn_t;
     43
    4044#endif
    4145/**
    4246 * @}
    4347 */
     48
  • uspace/drv/bus/usb/ehci/hw_struct/link_pointer.h

    r5b18137 rb4b534ac  
    11/*
    2  * Copyright (c) 2011 Vojtech Horky
     2 * Copyright (c) 2013 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    29 /** @addtogroup libusb
     28/** @addtogroup drvusbehci
    3029 * @{
    3130 */
    3231/** @file
    33  * Implementations of DDF interfaces functions.
     32 * @brief EHCI driver
    3433 */
    35 
    36 #ifndef LIBUSB_DDFIFACE_H_
    37 #define LIBUSB_DDFIFACE_H_
     34#ifndef DRV_EHCI_HW_STRUCT_LINK_POINTER_H
     35#define DRV_EHCI_HW_STRUCT_LINK_POINTER_H
    3836
    3937#include <sys/types.h>
    40 #include <usb_iface.h>
    4138
    42 extern int usb_iface_get_hc_handle_device_impl(ddf_fun_t *, devman_handle_t *);
    43 extern int usb_iface_get_my_address_forward_impl(ddf_fun_t *, usb_address_t *);
    44 extern usb_iface_t usb_iface_hub_impl;
     39/** EHCI link pointer, used by many data structures */
     40typedef volatile uint32_t link_pointer_t;
    4541
    46 extern int usb_iface_get_my_address_from_device_data(ddf_fun_t *, usb_address_t *);
    47 extern usb_iface_t usb_iface_hub_child_impl;
     42#define LINK_POINTER_ADDRESS_MASK   0xfffffff0 /* upper 28 bits */
    4843
    49 extern int usb_iface_get_hc_handle_hc_impl(ddf_fun_t *, devman_handle_t *);
     44#define LINK_POINTER_TERMINATE_FLAG   (1 << 0)
     45
     46enum {
     47        LINK_POINTER_TYPE_iTD  = 0x0 << 1,
     48        LINK_POINTER_TYPE_QH   = 0x1 << 1,
     49        LINK_POINTER_TYPE_siTD = 0x2 << 1,
     50        LINK_POINTER_TYPE_FSTN = 0x3 << 1,
     51        LINK_POINTER_TYPE_MASK = 0x3 << 1,
     52};
     53
     54#define LINK_POINTER_QH(address) \
     55        ((address & LINK_POINTER_ADDRESS_MASK) | LINK_POINTER_TYPE_QH)
     56
     57#define LINK_POINTER_TD(address) \
     58        (address & LINK_POINTER_ADDRESS_MASK)
     59
     60#define LINK_POINTER_TERM \
     61        ((link_pointer_t)LINK_POINTER_TERMINATE_FLAG)
    5062
    5163#endif
    52 
    5364/**
    5465 * @}
  • uspace/drv/bus/usb/ehci/hw_struct/mem_access.h

    r5b18137 rb4b534ac  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2013 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    29 /** @addtogroup drvusbuhcihc
     28/** @addtogroup drvusbehci
    3029 * @{
    3130 */
    3231/** @file
    33  * @brief UHCI driver PCI helper functions
     32 * @brief EHCI driver
    3433 */
    35 #ifndef DRV_UHCI_PCI_H
    36 #define DRV_UHCI_PCI_H
     34#ifndef DRV_EHCI_HW_MEM_ACCESS_H
     35#define DRV_EHCI_HW_MEM_ACCESS_H
    3736
    38 #include <ddf/driver.h>
    39 #include <device/hw_res_parsed.h>
     37#include <byteorder.h>
     38#include <libarch/barrier.h>
    4039
    41 int get_my_registers(ddf_dev_t *, addr_range_t *, int *);
    42 int enable_interrupts(ddf_dev_t *);
    43 int disable_legacy(ddf_dev_t *);
     40#define EHCI_MEM32_WR(reg, val) reg = host2uint32_t_le(val)
     41#define EHCI_MEM32_RD(reg) uint32_t_le2host(reg)
     42#define EHCI_MEM32_SET(reg, val) reg |= host2uint32_t_le(val)
     43#define EHCI_MEM32_CLR(reg, val) reg &= host2uint32_t_le(~val)
    4444
    4545#endif
    46 /**
     46
     47/*
    4748 * @}
    4849 */
  • uspace/drv/bus/usb/ehci/main.c

    r5b18137 rb4b534ac  
    3333 * Main routines of EHCI driver.
    3434 */
    35 
    3635#include <ddf/driver.h>
    3736#include <ddf/interrupt.h>
    3837#include <device/hw_res.h>
    3938#include <errno.h>
    40 #include <stdbool.h>
    4139#include <str_error.h>
     40#include <io/logctl.h>
    4241
    4342#include <usb_iface.h>
    44 #include <usb/ddfiface.h>
    4543#include <usb/debug.h>
    46 #include <usb/host/hcd.h>
     44#include <usb/host/ddf_helpers.h>
    4745
    4846#include "res.h"
     47#include "hc.h"
     48#include "ehci_endpoint.h"
    4949
    5050#define NAME "ehci"
    5151
    52 static int ehci_dev_add(ddf_dev_t *device);
     52static int ehci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool);
     53static void ehci_driver_fini(hcd_t *);
    5354
    54 static driver_ops_t ehci_driver_ops = {
    55         .dev_add = ehci_dev_add,
     55static const ddf_hc_driver_t ehci_hc_driver = {
     56        .claim = disable_legacy,
     57        .hc_speed = USB_SPEED_HIGH,
     58        .irq_code_gen = ehci_hc_gen_irq_code,
     59        .init = ehci_driver_init,
     60        .fini = ehci_driver_fini,
     61        .name = "EHCI-PCI",
     62        .ops = {
     63                .schedule       = ehci_hc_schedule,
     64                .ep_add_hook    = ehci_endpoint_init,
     65                .ep_remove_hook = ehci_endpoint_fini,
     66                .irq_hook       = ehci_hc_interrupt,
     67                .status_hook    = ehci_hc_status,
     68        }
    5669};
    5770
    58 static driver_t ehci_driver = {
    59         .name = NAME,
    60         .driver_ops = &ehci_driver_ops
    61 };
    62 static ddf_dev_ops_t hc_ops = {
    63         .interfaces[USBHC_DEV_IFACE] = &hcd_iface,
    64 };
    6571
     72static int ehci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, bool irq)
     73{
     74        assert(hcd);
     75        assert(hcd_get_driver_data(hcd) == NULL);
     76
     77        hc_t *instance = malloc(sizeof(hc_t));
     78        if (!instance)
     79                return ENOMEM;
     80
     81        const int ret = hc_init(instance, res, irq);
     82        if (ret == EOK) {
     83                hcd_set_implementation(hcd, instance, &ehci_hc_driver.ops);
     84        } else {
     85                free(instance);
     86        }
     87        return ret;
     88}
     89
     90static void ehci_driver_fini(hcd_t *hcd)
     91{
     92        assert(hcd);
     93        hc_t *hc = hcd_get_driver_data(hcd);
     94        if (hc)
     95                hc_fini(hc);
     96
     97        free(hc);
     98        hcd_set_implementation(hcd, NULL, NULL);
     99}
    66100
    67101/** Initializes a new ddf driver instance of EHCI hcd.
     
    72106static int ehci_dev_add(ddf_dev_t *device)
    73107{
    74         ddf_fun_t *hc_fun = NULL;
    75         bool fun_bound = false;
    76 
     108        usb_log_debug("ehci_dev_add() called\n");
    77109        assert(device);
    78110
    79         addr_range_t reg_range;
    80         int irq = 0;
     111        return hcd_ddf_add_hc(device, &ehci_hc_driver);
    81112
    82         int rc = get_my_registers(device, &reg_range, &irq);
    83         if (rc != EOK) {
    84                 usb_log_error("Failed to get memory addresses for %" PRIun
    85                     ": %s.\n", ddf_dev_get_handle(device), str_error(rc));
    86                 goto error;
    87         }
     113}
    88114
    89         usb_log_info("Memory mapped regs at %p (size %zu), IRQ %d.\n",
    90             RNGABSPTR(reg_range), RNGSZ(reg_range), irq);
    91115
    92         rc = disable_legacy(device, &reg_range);
    93         if (rc != EOK) {
    94                 usb_log_error("Failed to disable legacy USB: %s.\n",
    95                     str_error(rc));
    96                 goto error;
    97         }
     116static const driver_ops_t ehci_driver_ops = {
     117        .dev_add = ehci_dev_add,
     118};
    98119
    99         hc_fun = ddf_fun_create(device, fun_exposed, "ehci_hc");
    100         if (hc_fun == NULL) {
    101                 usb_log_error("Failed to create EHCI function.\n");
    102                 rc = ENOMEM;
    103                 goto error;
    104         }
     120static const driver_t ehci_driver = {
     121        .name = NAME,
     122        .driver_ops = &ehci_driver_ops
     123};
    105124
    106         hcd_t *ehci_hc = ddf_fun_data_alloc(hc_fun, sizeof(hcd_t));
    107         if (ehci_hc == NULL) {
    108                 usb_log_error("Failed to alloc generic HC driver.\n");
    109                 rc = ENOMEM;
    110                 goto error;
    111         }
    112 
    113         /* High Speed, no bandwidth */
    114         hcd_init(ehci_hc, USB_SPEED_HIGH, 0, NULL);
    115         ddf_fun_set_ops(hc_fun,  &hc_ops);
    116 
    117         rc = ddf_fun_bind(hc_fun);
    118         if (rc != EOK) {
    119                 usb_log_error("Failed to bind EHCI function: %s.\n",
    120                     str_error(rc));
    121                 goto error;
    122         }
    123 
    124         fun_bound = true;
    125 
    126         rc = ddf_fun_add_to_category(hc_fun, USB_HC_CATEGORY);
    127         if (rc != EOK) {
    128                 usb_log_error("Failed to add EHCI to HC class: %s.\n",
    129                     str_error(rc));
    130                 goto error;
    131         }
    132 
    133         usb_log_info("Controlling new EHCI device `%s' (handle %" PRIun ").\n",
    134             ddf_dev_get_name(device), ddf_dev_get_handle(device));
    135 
    136         return EOK;
    137 error:
    138         if (fun_bound)
    139                 ddf_fun_unbind(hc_fun);
    140         if (hc_fun != NULL)
    141                 ddf_fun_destroy(hc_fun);
    142         return rc;
    143 }
    144125
    145126/** Initializes global driver structures (NONE).
     
    154135{
    155136        log_init(NAME);
     137        logctl_set_log_level(NAME, LVL_NOTE);
    156138        return ddf_driver_main(&ehci_driver);
    157139}
  • uspace/drv/bus/usb/ehci/res.c

    r5b18137 rb4b534ac  
    4646
    4747#include "res.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)
     48#include "ehci_regs.h"
    6049
    6150#define USBLEGSUP_OFFSET 0
     
    6756#define WAIT_STEP 10
    6857
    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  */
    77 int 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             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  */
    114 int enable_interrupts(ddf_dev_t *device)
    115 {
    116         async_sess_t *parent_sess = devman_parent_device_connect(
    117             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 }
    126 
    12758/** Implements BIOS hands-off routine as described in EHCI spec
    12859 *
     
    13162 * @return Error code.
    13263 */
    133 static int disable_extended_caps(ddf_dev_t *device, unsigned eecp)
     64static int disable_extended_caps(async_sess_t *parent_sess, unsigned eecp)
    13465{
    13566        /* nothing to do */
     
    13768                return EOK;
    13869
    139         async_sess_t *parent_sess = devman_parent_device_connect(
    140             ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
    141         if (!parent_sess)
    142                 return ENOMEM;
    143 
    14470        /* Read the first EEC. i.e. Legacy Support register */
    14571        uint32_t usblegsup;
    146         int rc = pci_config_space_read_32(parent_sess,
     72        int ret = pci_config_space_read_32(parent_sess,
    14773            eecp + USBLEGSUP_OFFSET, &usblegsup);
    148         if (rc != EOK) {
    149                 usb_log_error("Failed to read USBLEGSUP: %s.\n",
    150                     str_error(rc));
    151                 goto error;
    152         }
    153 
    154         usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
     74        if (ret != EOK) {
     75                usb_log_error("Failed to read USBLEGSUP: %s.\n", str_error(ret));
     76                return ret;
     77        }
     78        usb_log_debug2("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
    15579
    15680        /* Request control from firmware/BIOS by writing 1 to highest
    15781         * byte. (OS Control semaphore)*/
    15882        usb_log_debug("Requesting OS control.\n");
    159         rc = pci_config_space_write_8(parent_sess,
     83        ret = pci_config_space_write_8(parent_sess,
    16084            eecp + USBLEGSUP_OFFSET + 3, 1);
    161         if (rc != EOK) {
     85        if (ret != EOK) {
    16286                usb_log_error("Failed to request OS EHCI control: %s.\n",
    163                     str_error(rc));
    164                 goto error;
     87                    str_error(ret));
     88                return ret;
    16589        }
    16690
    16791        size_t wait = 0;
    16892        /* Wait for BIOS to release control. */
    169         rc = pci_config_space_read_32(
     93        ret = pci_config_space_read_32(
    17094            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 
    177         while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
     95        while ((ret == EOK) && (wait < DEFAULT_WAIT)
     96            && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
    17897                async_usleep(WAIT_STEP);
    179                 rc = pci_config_space_read_32(parent_sess,
     98                ret = pci_config_space_read_32(parent_sess,
    18099                    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                 }
    186100                wait += WAIT_STEP;
    187101        }
     
    189103        if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) {
    190104                usb_log_info("BIOS released control after %zu usec.\n", wait);
    191                 async_hangup(parent_sess);
    192105                return EOK;
    193106        }
     
    196109        usb_log_warning( "BIOS failed to release control after "
    197110            "%zu usecs, force it.\n", wait);
    198         rc = pci_config_space_write_32(parent_sess,
     111        ret = pci_config_space_write_32(parent_sess,
    199112            eecp + USBLEGSUP_OFFSET, USBLEGSUP_OS_CONTROL);
    200         if (rc != EOK) {
    201                 usb_log_error("Failed to force OS control: "
    202                     "%s.\n", str_error(rc));
    203                 goto error;
     113        if (ret != EOK) {
     114                usb_log_error("Failed to force OS control: %s.\n",
     115                    str_error(ret));
     116                return ret;
    204117        }
    205118
     
    213126                /* Read the second EEC Legacy Support and Control register */
    214127                uint32_t usblegctlsts;
    215                 rc = pci_config_space_read_32(parent_sess,
     128                ret = pci_config_space_read_32(parent_sess,
    216129                    eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    217                 if (rc != EOK) {
     130                if (ret != EOK) {
    218131                        usb_log_error("Failed to get USBLEGCTLSTS: %s.\n",
    219                             str_error(rc));
    220                         goto error;
     132                            str_error(ret));
     133                        return ret;
    221134                }
    222 
    223                 usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n", usblegctlsts);
     135                usb_log_debug2("USBLEGCTLSTS: %" PRIx32 ".\n", usblegctlsts);
    224136                /*
    225137                 * Zero SMI enables in legacy control register.
     
    227139                 * interfering. NOTE: Three upper bits are WC
    228140                 */
    229                 rc = pci_config_space_write_32(parent_sess,
     141                ret = pci_config_space_write_32(parent_sess,
    230142                    eecp + USBLEGCTLSTS_OFFSET, 0xe0000000);
    231                 if (rc != EOK) {
    232                         usb_log_error("Failed(%d) zero USBLEGCTLSTS.\n", rc);
    233                         goto error;
     143                if (ret != EOK) {
     144                        usb_log_error("Failed to zero USBLEGCTLSTS: %s\n",
     145                            str_error(ret));
     146                        return ret;
    234147                }
    235148
    236149                udelay(10);
    237                 rc = pci_config_space_read_32(parent_sess,
     150                /* read again to amke sure it's zeroed */
     151                ret = pci_config_space_read_32(parent_sess,
    238152                    eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    239                 if (rc != EOK) {
     153                if (ret != EOK) {
    240154                        usb_log_error("Failed to get USBLEGCTLSTS 2: %s.\n",
    241                             str_error(rc));
    242                         goto error;
     155                            str_error(ret));
     156                        return ret;
    243157                }
    244 
    245                 usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n",
     158                usb_log_debug2("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n",
    246159                    usblegctlsts);
    247160        }
    248161
    249162        /* Read again Legacy Support register */
    250         rc = pci_config_space_read_32(parent_sess,
     163        ret = pci_config_space_read_32(parent_sess,
    251164            eecp + USBLEGSUP_OFFSET, &usblegsup);
    252         if (rc != EOK) {
     165        if (ret != EOK) {
    253166                usb_log_error("Failed to read USBLEGSUP: %s.\n",
    254                     str_error(rc));
    255                 goto error;
    256         }
    257 
    258         usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
    259         async_hangup(parent_sess);
    260         return EOK;
    261 error:
    262         async_hangup(parent_sess);
    263         return rc;
     167                    str_error(ret));
     168                return ret;
     169        }
     170        usb_log_debug2("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
     171        return ret;
    264172}
    265173
    266 int disable_legacy(ddf_dev_t *device, addr_range_t *reg_range)
     174int disable_legacy(ddf_dev_t *device)
    267175{
    268176        assert(device);
     177
     178        async_sess_t *parent_sess = devman_parent_device_connect(
     179            ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
     180        if (!parent_sess)
     181                return ENOMEM;
     182
    269183        usb_log_debug("Disabling EHCI legacy support.\n");
     184
     185        hw_res_list_parsed_t res;
     186        hw_res_list_parsed_init(&res);
     187        int ret = hw_res_get_list_parsed(parent_sess, &res, 0);
     188        if (ret != EOK) {
     189                usb_log_error("Failed to get resource list: %s\n",
     190                    str_error(ret));
     191                goto clean;
     192        }
     193
     194        if (res.mem_ranges.count < 1) {
     195                usb_log_error("Incorrect mem range count: %zu",
     196                    res.mem_ranges.count);
     197                ret = EINVAL;
     198                goto clean;
     199        }
    270200
    271201        /* Map EHCI registers */
    272202        void *regs = NULL;
    273         int rc = pio_enable_range(reg_range, &regs);
    274         if (rc != EOK) {
     203        ret = pio_enable_range(&res.mem_ranges.ranges[0], &regs);
     204        if (ret != EOK) {
    275205                usb_log_error("Failed to map registers %p: %s.\n",
    276                     RNGABSPTR(*reg_range), str_error(rc));
    277                 return rc;
    278         }
    279 
    280         usb_log_debug2("Registers mapped at: %p.\n", regs);
    281 
    282         const uint32_t hcc_params =
    283             *(uint32_t*)(regs + HCC_PARAMS_OFFSET);
    284         usb_log_debug("Value of hcc params register: %x.\n", hcc_params);
     206                    RNGABSPTR(res.mem_ranges.ranges[0]), str_error(ret));
     207                goto clean;
     208        }
     209
     210        usb_log_debug("Registers mapped at: %p.\n", regs);
     211
     212        ehci_caps_regs_t *ehci_caps = regs;
     213
     214        const uint32_t hcc_params = EHCI_RD(ehci_caps->hccparams);
     215        usb_log_debug2("Value of hcc params register: %x.\n", hcc_params);
    285216
    286217        /* Read value of EHCI Extended Capabilities Pointer
    287218         * position of EEC registers (points to PCI config space) */
    288219        const uint32_t eecp =
    289             (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;
    290         usb_log_debug("Value of EECP: %x.\n", eecp);
    291 
    292         rc = disable_extended_caps(device, eecp);
    293         if (rc != EOK) {
     220            (hcc_params >> EHCI_CAPS_HCC_EECP_SHIFT) & EHCI_CAPS_HCC_EECP_MASK;
     221        usb_log_debug2("Value of EECP: %x.\n", eecp);
     222
     223        ret = disable_extended_caps(parent_sess, eecp);
     224        if (ret != EOK) {
    294225                usb_log_error("Failed to disable extended capabilities: %s.\n",
    295                     str_error(rc));
    296                 return rc;
    297         }
    298 
    299         /*
    300          * TURN OFF EHCI FOR NOW, DRIVER WILL REINITIALIZE IT IF NEEDED
    301          */
    302 
    303         /* Get size of capability registers in memory space. */
    304         const unsigned operation_offset = *(uint8_t*)regs;
    305         usb_log_debug("USBCMD offset: %d.\n", operation_offset);
    306 
    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;
    323                 /* Wait until hc is halted */
    324                 while ((*usbsts & USBSTS_HALTED) == 0);
    325                 usb_log_info("EHCI turned off.\n");
    326         } else {
    327                 usb_log_info("EHCI was not running.\n");
    328         }
    329         usb_log_debug("Registers: \n"
    330             "\t USBCMD(%p): %x(0x00080000 = at least 1ms between interrupts)\n"
    331             "\t USBSTS(%p): %x(0x00001000 = HC halted)\n"
    332             "\t USBINT(%p): %x(0x0 = no interrupts).\n"
    333             "\t CONFIG(%p): %x(0x0 = ports controlled by companion hc).\n",
    334             usbcmd, *usbcmd, usbsts, *usbsts, usbint, *usbint, usbconf,*usbconf);
    335 
    336         return rc;
     226                    str_error(ret));
     227                    goto clean;
     228        }
     229clean:
     230        //TODO unmap registers
     231        hw_res_list_parsed_clean(&res);
     232        async_hangup(parent_sess);
     233        return ret;
    337234}
    338235
  • uspace/drv/bus/usb/ehci/res.h

    r5b18137 rb4b534ac  
    3939#include <device/hw_res_parsed.h>
    4040
    41 int get_my_registers(ddf_dev_t *, addr_range_t *, int *);
    42 int enable_interrupts(ddf_dev_t *);
    43 int disable_legacy(ddf_dev_t *, addr_range_t *);
     41int disable_legacy(ddf_dev_t *);
    4442
    4543#endif
Note: See TracChangeset for help on using the changeset viewer.