Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/ehci-hcd/pci.c

    r0d3167e r40a5d40  
    4848
    4949#define PAGE_SIZE_MASK 0xfffff000
    50 
    5150#define HCC_PARAMS_OFFSET 0x8
    5251#define HCC_PARAMS_EECP_MASK 0xff
    5352#define HCC_PARAMS_EECP_OFFSET 8
    54 
    55 #define CMD_OFFSET 0x0
    56 #define CONFIGFLAG_OFFSET 0x40
    5753
    5854#define USBCMD_RUN 1
     
    6662#define WAIT_STEP 10
    6763
     64
    6865/** Get address of registers and IRQ for given device.
    6966 *
    7067 * @param[in] dev Device asking for the addresses.
    71  * @param[out] mem_reg_address Base address of the memory range.
    72  * @param[out] mem_reg_size Size of the memory range.
     68 * @param[out] io_reg_address Base address of the I/O range.
     69 * @param[out] io_reg_size Size of the I/O range.
    7370 * @param[out] irq_no IRQ assigned to the device.
    7471 * @return Error code.
     
    9087        rc = hw_res_get_resource_list(parent_phone, &hw_resources);
    9188        if (rc != EOK) {
    92                 async_hangup(parent_phone);
    93                 return rc;
     89                goto leave;
    9490        }
    9591
     
    104100        for (i = 0; i < hw_resources.count; i++) {
    105101                hw_resource_t *res = &hw_resources.resources[i];
    106                 switch (res->type)
    107                 {
    108                 case INTERRUPT:
    109                         irq = res->res.interrupt.irq;
    110                         irq_found = true;
    111                         usb_log_debug2("Found interrupt: %d.\n", irq);
    112                         break;
    113 
    114                 case MEM_RANGE:
    115                         if (res->res.mem_range.address != 0
    116                             && res->res.mem_range.size != 0 ) {
    117                                 mem_address = res->res.mem_range.address;
    118                                 mem_size = res->res.mem_range.size;
    119                                 usb_log_debug2("Found mem: %llx %zu.\n",
    120                                     mem_address, mem_size);
    121                                 mem_found = true;
     102                switch (res->type) {
     103                        case INTERRUPT:
     104                                irq = res->res.interrupt.irq;
     105                                irq_found = true;
     106                                usb_log_debug2("Found interrupt: %d.\n", irq);
     107                                break;
     108                        case MEM_RANGE:
     109                                if (res->res.mem_range.address != 0
     110                                    && res->res.mem_range.size != 0 ) {
     111                                        mem_address = res->res.mem_range.address;
     112                                        mem_size = res->res.mem_range.size;
     113                                        usb_log_debug2("Found mem: %llx %zu.\n",
     114                                                        res->res.mem_range.address, res->res.mem_range.size);
     115                                        mem_found = true;
    122116                                }
    123                 default:
    124                         break;
     117                                break;
     118                        default:
     119                                break;
    125120                }
    126121        }
    127122
    128         if (mem_found && irq_found) {
    129                 *mem_reg_address = mem_address;
    130                 *mem_reg_size = mem_size;
    131                 *irq_no = irq;
    132                 rc = EOK;
    133         } else {
     123        if (!mem_found) {
    134124                rc = ENOENT;
    135         }
    136 
     125                goto leave;
     126        }
     127
     128        if (!irq_found) {
     129                rc = ENOENT;
     130                goto leave;
     131        }
     132
     133        *mem_reg_address = mem_address;
     134        *mem_reg_size = mem_size;
     135        *irq_no = irq;
     136
     137        rc = EOK;
     138leave:
    137139        async_hangup(parent_phone);
     140
    138141        return rc;
    139142}
    140143/*----------------------------------------------------------------------------*/
    141 /** Calls the PCI driver with a request to enable interrupts
    142  *
    143  * @param[in] device Device asking for interrupts
    144  * @return Error code.
    145  */
    146144int pci_enable_interrupts(ddf_dev_t *device)
    147145{
    148         int parent_phone =
    149             devman_parent_device_connect(device->handle, IPC_FLAG_BLOCKING);
    150         if (parent_phone < 0) {
    151                 return parent_phone;
    152         }
     146        int parent_phone = devman_parent_device_connect(device->handle,
     147            IPC_FLAG_BLOCKING);
    153148        bool enabled = hw_res_enable_interrupt(parent_phone);
    154149        async_hangup(parent_phone);
     
    156151}
    157152/*----------------------------------------------------------------------------*/
    158 /** Implements BIOS handoff routine as decribed in EHCI spec
    159  *
    160  * @param[in] device Device asking for interrupts
    161  * @return Error code.
    162  */
    163153int pci_disable_legacy(ddf_dev_t *device)
    164154{
     
    170160        }
    171161
    172 #define CHECK_RET_HANGUP_RETURN(ret, message...) \
    173         if (ret != EOK) { \
    174                 usb_log_error(message); \
    175                 async_hangup(parent_phone); \
    176                 return ret; \
    177         } else (void)0
    178 
    179 
    180         /* read register space BASE BAR */
     162        /* read register space BAR */
    181163        sysarg_t address = 0x10;
    182164        sysarg_t value;
    183165
    184         int ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     166  int ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    185167            IPC_M_CONFIG_SPACE_READ_32, address, &value);
    186         CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read PCI config space.\n",
    187             ret);
    188168        usb_log_info("Register space BAR at %p:%x.\n", address, value);
    189169
    190         /* clear lower byte, it's not part of the BASE address */
     170        /* clear lower byte, it's not part of the address */
    191171        uintptr_t registers = (value & 0xffffff00);
    192         usb_log_info("Memory registers BASE address:%p.\n", registers);
    193 
    194         /* if nothing setup the hc, we don't need to turn it off */
     172        usb_log_info("Mem register address:%p.\n", registers);
     173
     174        /* if nothing setup the hc, the we don't need to to turn it off */
    195175        if (registers == 0)
    196176                return ENOTSUP;
    197177
    198         /* map EHCI registers */
     178        /* EHCI registers need 20 bytes*/
    199179        void *regs = as_get_mappable_page(4096);
    200180        ret = physmem_map((void*)(registers & PAGE_SIZE_MASK), regs, 1,
    201181            AS_AREA_READ | AS_AREA_WRITE);
    202         CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to map registers %p:%p.\n",
    203             ret, regs, registers);
    204 
     182        if (ret != EOK) {
     183                usb_log_error("Failed(%d) to map registers %p:%p.\n",
     184                    ret, regs, registers);
     185        }
    205186        /* calculate value of BASE */
    206187        registers = (registers & 0xf00) | (uintptr_t)regs;
    207188
    208         const uint32_t hcc_params =
    209             *(uint32_t*)(registers + HCC_PARAMS_OFFSET);
     189        uint32_t hcc_params = *(uint32_t*)(registers + HCC_PARAMS_OFFSET);
     190
    210191        usb_log_debug("Value of hcc params register: %x.\n", hcc_params);
    211 
    212         /* Read value of EHCI Extended Capabilities Pointer
    213          * (points to PCI config space) */
    214         uint32_t eecp =
    215             (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;
     192        uint32_t eecp = (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;
    216193        usb_log_debug("Value of EECP: %x.\n", eecp);
    217194
    218         /* Read the second EEC. i.e. Legacy Support and Control register */
    219         /* TODO: Check capability type here */
    220195        ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    221196            IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGCTLSTS_OFFSET, &value);
    222         CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGCTLSTS.\n", ret);
    223         usb_log_debug("USBLEGCTLSTS: %x.\n", value);
    224 
    225         /* Read the first EEC. i.e. Legacy Support register */
    226         /* TODO: Check capability type here */
     197        if (ret != EOK) {
     198                usb_log_error("Failed(%d) to read USBLEGCTLSTS.\n", ret);
     199                return ret;
     200        }
     201        usb_log_debug2("USBLEGCTLSTS: %x.\n", value);
     202
    227203        ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    228204            IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
    229         CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret);
     205        if (ret != EOK) {
     206                usb_log_error("Failed(%d) to read USBLEGSUP.\n", ret);
     207                return ret;
     208        }
    230209        usb_log_debug2("USBLEGSUP: %x.\n", value);
    231210
    232         /* Request control from firmware/BIOS, by writing 1 to highest byte.
    233          * (OS Control semaphore)*/
     211        /* request control from firmware/BIOS, by writing 1 to highest byte */
    234212        ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    235213           IPC_M_CONFIG_SPACE_WRITE_8, eecp + USBLEGSUP_OFFSET + 3, 1);
    236         CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to request OS EHCI control.\n",
    237             ret);
    238 
    239         size_t wait = 0;
    240         /* Wait for BIOS to release control. */
     214        if (ret != EOK) {
     215                usb_log_error("Failed(%d) request OS EHCI control.\n", ret);
     216                return ret;
     217        }
     218
     219        size_t wait = 0; /* might be anything */
     220        /* wait for BIOS to release control */
    241221        while ((wait < DEFAULT_WAIT) && (value & USBLEGSUP_BIOS_CONTROL)) {
    242222                async_usleep(WAIT_STEP);
    243223                ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    244                     IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
     224                                IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
    245225                wait += WAIT_STEP;
    246226        }
    247227
    248 
    249228        if ((value & USBLEGSUP_BIOS_CONTROL) != 0) {
    250                 usb_log_info("BIOS released control after %d usec.\n", wait);
     229                usb_log_warning(
     230                    "BIOS failed to release control after %d usecs, force it.\n",
     231                    wait);
     232                ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     233                          IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGSUP_OFFSET,
     234                    USBLEGSUP_OS_CONTROL);
     235                if (ret != EOK) {
     236                        usb_log_error("Failed(%d) to force OS EHCI control.\n", ret);
     237                        return ret;
     238                }
    251239        } else {
    252                 /* BIOS failed to hand over control, this should not happen. */
    253                 usb_log_warning( "BIOS failed to release control after"
    254                     "%d usecs, force it.\n", wait);
    255                 ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    256                     IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGSUP_OFFSET,
    257                     USBLEGSUP_OS_CONTROL);
    258                 CHECK_RET_HANGUP_RETURN(ret,
    259                     "Failed(%d) to force OS EHCI control.\n", ret);
    260                 /* TODO: This does not seem to work on my machine */
    261         }
    262 
    263         /* Zero SMI enables in legacy control register.
    264          * It would prevent pre-OS code from interfering. */
     240                usb_log_info("BIOS released control after %d usec.\n",
     241                    wait);
     242        }
     243
     244
     245        /* zero SMI enables in legacy control register */
    265246        ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    266247           IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGCTLSTS_OFFSET, 0);
    267         CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) zero USBLEGCTLSTS.\n", ret);
     248        if (ret != EOK) {
     249                usb_log_error("Failed(%d) zero USBLEGCTLSTS.\n", ret);
     250                return ret;
     251        }
    268252        usb_log_debug("Zeroed USBLEGCTLSTS register.\n");
    269253
    270         /* Read again Legacy Support and Control register */
    271254        ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    272255            IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGCTLSTS_OFFSET, &value);
    273         CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGCTLSTS.\n", ret);
     256        if (ret != EOK) {
     257                usb_log_error("Failed(%d) to read USBLEGCTLSTS.\n", ret);
     258                return ret;
     259        }
    274260        usb_log_debug2("USBLEGCTLSTS: %x.\n", value);
    275261
    276         /* Read again Legacy Support register */
    277262        ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    278263            IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
    279         CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret);
     264        if (ret != EOK) {
     265                usb_log_error("Failed(%d) to read USBLEGSUP.\n", ret);
     266                return ret;
     267        }
    280268        usb_log_debug2("USBLEGSUP: %x.\n", value);
    281269
     
    284272 */
    285273
    286         /* Get size of capability registers in memory space. */
     274        /* size of capability registers in memory space */
    287275        uint8_t operation_offset = *(uint8_t*)registers;
    288276        usb_log_debug("USBCMD offset: %d.\n", operation_offset);
    289 
    290         /* Zero USBCMD register. */
     277        /* zero USBCMD register */
    291278        volatile uint32_t *usbcmd =
    292             (uint32_t*)((uint8_t*)registers + operation_offset + CMD_OFFSET);
    293         volatile uint32_t *usbconfigured =
    294             (uint32_t*)((uint8_t*)registers + operation_offset
    295             + CONFIGFLAG_OFFSET);
     279         (uint32_t*)((uint8_t*)registers + operation_offset);
    296280        usb_log_debug("USBCMD value: %x.\n", *usbcmd);
    297281        if (*usbcmd & USBCMD_RUN) {
    298282                *usbcmd = 0;
    299                 *usbconfigured = 0;
    300283                usb_log_info("EHCI turned off.\n");
    301284        } else {
     
    303286        }
    304287
     288
    305289        async_hangup(parent_phone);
    306         return ret;
    307 #undef CHECK_RET_HANGUP_RETURN
     290
     291  return ret;
    308292}
    309293/*----------------------------------------------------------------------------*/
Note: See TracChangeset for help on using the changeset viewer.