Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ohci/hc.c

    r56fd7cf r7de1988c  
    3535
    3636#include <errno.h>
     37#include <stdbool.h>
    3738#include <str_error.h>
    3839#include <adt/list.h>
     
    8384};
    8485
     86enum {
     87        /** Number of PIO ranges used in IRQ code */
     88        hc_irq_pio_range_count =
     89            sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t),
     90
     91        /** Number of commands used in IRQ code */
     92        hc_irq_cmd_count =
     93            sizeof(ohci_irq_commands) / sizeof(irq_cmd_t)
     94};
     95
    8596static void hc_gain_control(hc_t *instance);
    8697static void hc_start(hc_t *instance);
     
    90101static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    91102
    92 /** Get number of PIO ranges used in IRQ code.
    93  * @return Number of ranges.
    94  */
    95 size_t hc_irq_pio_range_count(void)
    96 {
    97         return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t);
    98 }
    99 
    100 /** Get number of commands used in IRQ code.
    101  * @return Number of commands.
    102  */
    103 size_t hc_irq_cmd_count(void)
    104 {
    105         return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t);
    106 }
    107 
    108103/** Generate IRQ code.
    109104 * @param[out] ranges PIO ranges buffer.
     
    111106 * @param[out] cmds Commands buffer.
    112107 * @param[in] cmds_size Size of the commands buffer (bytes).
    113  * @param[in] regs Physical address of device's registers.
    114  * @param[in] reg_size Size of the register area (bytes).
     108 * @param[in] regs Device's register range.
    115109 *
    116110 * @return Error code.
     
    118112int
    119113hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[],
    120     size_t cmds_size, uintptr_t regs, size_t reg_size)
     114    size_t cmds_size, addr_range_t *regs)
    121115{
    122116        if ((ranges_size < sizeof(ohci_pio_ranges)) ||
    123117            (cmds_size < sizeof(ohci_irq_commands)) ||
    124             (reg_size < sizeof(ohci_regs_t)))
     118            (RNGSZ(*regs) < sizeof(ohci_regs_t)))
    125119                return EOVERFLOW;
    126120
    127121        memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges));
    128         ranges[0].base = regs;
     122        ranges[0].base = RNGABS(*regs);
    129123
    130124        memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
    131         ohci_regs_t *registers = (ohci_regs_t *) regs;
     125        ohci_regs_t *registers = (ohci_regs_t *) RNGABSPTR(*regs);
    132126        cmds[0].addr = (void *) &registers->interrupt_status;
    133127        cmds[3].addr = (void *) &registers->interrupt_status;
     
    137131}
    138132
     133/** Register interrupt handler.
     134 *
     135 * @param[in] device Host controller DDF device
     136 * @param[in] regs Register range
     137 * @param[in] irq Interrupt number
     138 * @paran[in] handler Interrupt handler
     139 *
     140 * @return EOK on success or negative error code
     141 */
     142int hc_register_irq_handler(ddf_dev_t *device, addr_range_t *regs, int irq,
     143    interrupt_handler_t handler)
     144{
     145        int rc;
     146
     147        irq_pio_range_t irq_ranges[hc_irq_pio_range_count];
     148        irq_cmd_t irq_cmds[hc_irq_cmd_count];
     149
     150        irq_code_t irq_code = {
     151                .rangecount = hc_irq_pio_range_count,
     152                .ranges = irq_ranges,
     153                .cmdcount = hc_irq_cmd_count,
     154                .cmds = irq_cmds
     155        };
     156
     157        rc = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,
     158            sizeof(irq_cmds), regs);
     159        if (rc != EOK) {
     160                usb_log_error("Failed to generate IRQ code: %s.\n",
     161                    str_error(rc));
     162                return rc;
     163        }
     164
     165        /* Register handler to avoid interrupt lockup */
     166        rc = register_interrupt_handler(device, irq, handler, &irq_code);
     167        if (rc != EOK) {
     168                usb_log_error("Failed to register interrupt handler: %s.\n",
     169                    str_error(rc));
     170                return rc;
     171        }
     172
     173        return EOK;
     174}
     175
    139176/** Announce OHCI root hub to the DDF
    140177 *
     
    145182int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
    146183{
     184        bool addr_reqd = false;
     185        bool ep_added = false;
     186        bool fun_bound = false;
     187        int rc;
     188
    147189        assert(instance);
    148190        assert(hub_fun);
     
    150192        /* Try to get address 1 for root hub. */
    151193        instance->rh.address = 1;
    152         int ret = usb_device_manager_request_address(
     194        rc = usb_device_manager_request_address(
    153195            &instance->generic.dev_manager, &instance->rh.address, false,
    154196            USB_SPEED_FULL);
    155         if (ret != EOK) {
     197        if (rc != EOK) {
    156198                usb_log_error("Failed to get OHCI root hub address: %s\n",
    157                     str_error(ret));
    158                 return ret;
    159         }
    160 
    161 #define CHECK_RET_UNREG_RETURN(ret, message...) \
    162 if (ret != EOK) { \
    163         usb_log_error(message); \
    164         usb_endpoint_manager_remove_ep( \
    165             &instance->generic.ep_manager, instance->rh.address, 0, \
    166             USB_DIRECTION_BOTH, NULL, NULL); \
    167         usb_device_manager_release_address( \
    168             &instance->generic.dev_manager, instance->rh.address); \
    169         return ret; \
    170 } else (void)0
    171 
    172         ret = usb_endpoint_manager_add_ep(
     199                    str_error(rc));
     200                goto error;
     201        }
     202
     203        addr_reqd = true;
     204
     205        rc = usb_endpoint_manager_add_ep(
    173206            &instance->generic.ep_manager, instance->rh.address, 0,
    174207            USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64,
    175208            0, NULL, NULL);
    176         CHECK_RET_UNREG_RETURN(ret,
    177             "Failed to register root hub control endpoint: %s.\n",
    178             str_error(ret));
    179 
    180         ret = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100);
    181         CHECK_RET_UNREG_RETURN(ret,
    182             "Failed to add root hub match-id: %s.\n", str_error(ret));
    183 
    184         ret = ddf_fun_bind(hub_fun);
    185         CHECK_RET_UNREG_RETURN(ret,
    186             "Failed to bind root hub function: %s.\n", str_error(ret));
    187 
    188         ret = usb_device_manager_bind_address(&instance->generic.dev_manager,
     209        if (rc != EOK) {
     210                usb_log_error("Failed to register root hub control endpoint: %s.\n",
     211                    str_error(rc));
     212                goto error;
     213        }
     214
     215        ep_added = true;
     216
     217        rc = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100);
     218        if (rc != EOK) {
     219                usb_log_error("Failed to add root hub match-id: %s.\n",
     220                    str_error(rc));
     221                goto error;
     222        }
     223
     224        rc = ddf_fun_bind(hub_fun);
     225        if (rc != EOK) {
     226                usb_log_error("Failed to bind root hub function: %s.\n",
     227                    str_error(rc));
     228                goto error;
     229        }
     230
     231        fun_bound = true;
     232
     233        rc = usb_device_manager_bind_address(&instance->generic.dev_manager,
    189234            instance->rh.address, ddf_fun_get_handle(hub_fun));
    190         if (ret != EOK)
     235        if (rc != EOK) {
    191236                usb_log_warning("Failed to bind root hub address: %s.\n",
    192                     str_error(ret));
    193 
    194         return EOK;
    195 #undef CHECK_RET_RELEASE
     237                    str_error(rc));
     238        }
     239
     240        return EOK;
     241error:
     242        if (fun_bound)
     243                ddf_fun_unbind(hub_fun);
     244        if (ep_added) {
     245                usb_endpoint_manager_remove_ep(
     246                    &instance->generic.ep_manager, instance->rh.address, 0,
     247                    USB_DIRECTION_BOTH, NULL, NULL);
     248        }
     249        if (addr_reqd) {
     250                usb_device_manager_release_address(
     251                    &instance->generic.dev_manager, instance->rh.address);
     252        }
     253        return rc;
    196254}
    197255
     
    199257 *
    200258 * @param[in] instance Memory place for the structure.
    201  * @param[in] regs Address of the memory mapped I/O registers.
    202  * @param[in] reg_size Size of the memory mapped area.
     259 * @param[in] regs Device's I/O registers range.
    203260 * @param[in] interrupts True if w interrupts should be used
    204261 * @return Error code
    205262 */
    206 int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts)
    207 {
    208         assert(instance);
    209 
    210 #define CHECK_RET_RETURN(ret, message...) \
    211 if (ret != EOK) { \
    212         usb_log_error(message); \
    213         return ret; \
    214 } else (void)0
    215 
    216         int ret =
    217             pio_enable((void*)regs, reg_size, (void**)&instance->registers);
    218         CHECK_RET_RETURN(ret,
    219             "Failed to gain access to device registers: %s.\n", str_error(ret));
     263int hc_init(hc_t *instance, addr_range_t *regs, bool interrupts)
     264{
     265        assert(instance);
     266
     267        int rc = pio_enable_range(regs, (void **) &instance->registers);
     268        if (rc != EOK) {
     269                usb_log_error("Failed to gain access to device registers: %s.\n",
     270                    str_error(rc));
     271                return rc;
     272        }
    220273
    221274        list_initialize(&instance->pending_batches);
     
    228281        instance->generic.ep_remove_hook = ohci_endpoint_fini;
    229282
    230         ret = hc_init_memory(instance);
    231         CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures: %s.\n",
    232             str_error(ret));
    233 #undef CHECK_RET_RETURN
     283        rc = hc_init_memory(instance);
     284        if (rc != EOK) {
     285                usb_log_error("Failed to create OHCI memory structures: %s.\n",
     286                    str_error(rc));
     287                return rc;
     288        }
    234289
    235290        fibril_mutex_initialize(&instance->guard);
     
    602657        assert(instance);
    603658
    604         bzero(&instance->rh, sizeof(instance->rh));
     659        memset(&instance->rh, 0, sizeof(instance->rh));
    605660        /* Init queues */
    606661        const int ret = hc_init_transfer_lists(instance);
Note: See TracChangeset for help on using the changeset viewer.