Ignore:
File:
1 edited

Legend:

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

    r7de1988c r56fd7cf  
    3535
    3636#include <errno.h>
    37 #include <stdbool.h>
    3837#include <str_error.h>
    3938#include <adt/list.h>
     
    8483};
    8584
    86 enum {
    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 
    9685static void hc_gain_control(hc_t *instance);
    9786static void hc_start(hc_t *instance);
     
    10190static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    10291
     92/** Get number of PIO ranges used in IRQ code.
     93 * @return Number of ranges.
     94 */
     95size_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 */
     103size_t hc_irq_cmd_count(void)
     104{
     105        return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t);
     106}
     107
    103108/** Generate IRQ code.
    104109 * @param[out] ranges PIO ranges buffer.
     
    106111 * @param[out] cmds Commands buffer.
    107112 * @param[in] cmds_size Size of the commands buffer (bytes).
    108  * @param[in] regs Device's register range.
     113 * @param[in] regs Physical address of device's registers.
     114 * @param[in] reg_size Size of the register area (bytes).
    109115 *
    110116 * @return Error code.
     
    112118int
    113119hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[],
    114     size_t cmds_size, addr_range_t *regs)
     120    size_t cmds_size, uintptr_t regs, size_t reg_size)
    115121{
    116122        if ((ranges_size < sizeof(ohci_pio_ranges)) ||
    117123            (cmds_size < sizeof(ohci_irq_commands)) ||
    118             (RNGSZ(*regs) < sizeof(ohci_regs_t)))
     124            (reg_size < sizeof(ohci_regs_t)))
    119125                return EOVERFLOW;
    120126
    121127        memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges));
    122         ranges[0].base = RNGABS(*regs);
     128        ranges[0].base = regs;
    123129
    124130        memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
    125         ohci_regs_t *registers = (ohci_regs_t *) RNGABSPTR(*regs);
     131        ohci_regs_t *registers = (ohci_regs_t *) regs;
    126132        cmds[0].addr = (void *) &registers->interrupt_status;
    127133        cmds[3].addr = (void *) &registers->interrupt_status;
     
    131137}
    132138
    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  */
    142 int 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 
    176139/** Announce OHCI root hub to the DDF
    177140 *
     
    182145int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
    183146{
    184         bool addr_reqd = false;
    185         bool ep_added = false;
    186         bool fun_bound = false;
    187         int rc;
    188 
    189147        assert(instance);
    190148        assert(hub_fun);
     
    192150        /* Try to get address 1 for root hub. */
    193151        instance->rh.address = 1;
    194         rc = usb_device_manager_request_address(
     152        int ret = usb_device_manager_request_address(
    195153            &instance->generic.dev_manager, &instance->rh.address, false,
    196154            USB_SPEED_FULL);
    197         if (rc != EOK) {
     155        if (ret != EOK) {
    198156                usb_log_error("Failed to get OHCI root hub address: %s\n",
    199                     str_error(rc));
    200                 goto error;
    201         }
    202 
    203         addr_reqd = true;
    204 
    205         rc = usb_endpoint_manager_add_ep(
     157                    str_error(ret));
     158                return ret;
     159        }
     160
     161#define CHECK_RET_UNREG_RETURN(ret, message...) \
     162if (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(
    206173            &instance->generic.ep_manager, instance->rh.address, 0,
    207174            USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64,
    208175            0, NULL, NULL);
    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,
     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,
    234189            instance->rh.address, ddf_fun_get_handle(hub_fun));
    235         if (rc != EOK) {
     190        if (ret != EOK)
    236191                usb_log_warning("Failed to bind root hub address: %s.\n",
    237                     str_error(rc));
    238         }
     192                    str_error(ret));
    239193
    240194        return EOK;
    241 error:
    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;
     195#undef CHECK_RET_RELEASE
    254196}
    255197
     
    257199 *
    258200 * @param[in] instance Memory place for the structure.
    259  * @param[in] regs Device's I/O registers range.
     201 * @param[in] regs Address of the memory mapped I/O registers.
     202 * @param[in] reg_size Size of the memory mapped area.
    260203 * @param[in] interrupts True if w interrupts should be used
    261204 * @return Error code
    262205 */
    263 int 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         }
     206int 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...) \
     211if (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));
    273220
    274221        list_initialize(&instance->pending_batches);
     
    281228        instance->generic.ep_remove_hook = ohci_endpoint_fini;
    282229
    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         }
     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
    289234
    290235        fibril_mutex_initialize(&instance->guard);
     
    657602        assert(instance);
    658603
    659         memset(&instance->rh, 0, sizeof(instance->rh));
     604        bzero(&instance->rh, sizeof(instance->rh));
    660605        /* Init queues */
    661606        const int ret = hc_init_transfer_lists(instance);
Note: See TracChangeset for help on using the changeset viewer.