Ignore:
File:
1 edited

Legend:

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

    r7de1988c r6340a6ff  
    3535
    3636#include <errno.h>
    37 #include <stdbool.h>
    3837#include <str_error.h>
    3938#include <adt/list.h>
     
    4241#include <usb/debug.h>
    4342#include <usb/usb.h>
    44 #include <usb/ddfiface.h>
    4543
    4644#include "hc.h"
     
    8482};
    8583
    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 
    9684static void hc_gain_control(hc_t *instance);
    9785static void hc_start(hc_t *instance);
     
    9987static int hc_init_memory(hc_t *instance);
    10088static int interrupt_emulator(hc_t *instance);
    101 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
     89
     90/** Get number of PIO ranges used in IRQ code.
     91 * @return Number of ranges.
     92 */
     93size_t hc_irq_pio_range_count(void)
     94{
     95        return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t);
     96}
     97
     98/** Get number of commands used in IRQ code.
     99 * @return Number of commands.
     100 */
     101size_t hc_irq_cmd_count(void)
     102{
     103        return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t);
     104}
    102105
    103106/** Generate IRQ code.
     
    106109 * @param[out] cmds Commands buffer.
    107110 * @param[in] cmds_size Size of the commands buffer (bytes).
    108  * @param[in] regs Device's register range.
     111 * @param[in] regs Physical address of device's registers.
     112 * @param[in] reg_size Size of the register area (bytes).
    109113 *
    110114 * @return Error code.
     
    112116int
    113117hc_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)
     118    size_t cmds_size, uintptr_t regs, size_t reg_size)
    115119{
    116120        if ((ranges_size < sizeof(ohci_pio_ranges)) ||
    117121            (cmds_size < sizeof(ohci_irq_commands)) ||
    118             (RNGSZ(*regs) < sizeof(ohci_regs_t)))
     122            (reg_size < sizeof(ohci_regs_t)))
    119123                return EOVERFLOW;
    120124
    121125        memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges));
    122         ranges[0].base = RNGABS(*regs);
     126        ranges[0].base = regs;
    123127
    124128        memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
    125         ohci_regs_t *registers = (ohci_regs_t *) RNGABSPTR(*regs);
     129        ohci_regs_t *registers = (ohci_regs_t *) regs;
    126130        cmds[0].addr = (void *) &registers->interrupt_status;
    127131        cmds[3].addr = (void *) &registers->interrupt_status;
     
    131135}
    132136
    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 
    176 /** Announce OHCI root hub to the DDF
    177  *
    178  * @param[in] instance OHCI driver intance
    179  * @param[in] hub_fun DDF fuction representing OHCI root hub
    180  * @return Error code
    181  */
    182 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
    183 {
    184         bool addr_reqd = false;
    185         bool ep_added = false;
    186         bool fun_bound = false;
    187         int rc;
    188 
    189         assert(instance);
    190         assert(hub_fun);
    191 
    192         /* Try to get address 1 for root hub. */
    193         instance->rh.address = 1;
    194         rc = usb_device_manager_request_address(
    195             &instance->generic.dev_manager, &instance->rh.address, false,
    196             USB_SPEED_FULL);
    197         if (rc != EOK) {
    198                 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(
    206             &instance->generic.ep_manager, instance->rh.address, 0,
    207             USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64,
    208             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,
    234             instance->rh.address, ddf_fun_get_handle(hub_fun));
    235         if (rc != EOK) {
    236                 usb_log_warning("Failed to bind root hub address: %s.\n",
    237                     str_error(rc));
    238         }
    239 
    240         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;
    254 }
    255 
    256137/** Initialize OHCI hc driver structure
    257138 *
    258139 * @param[in] instance Memory place for the structure.
    259  * @param[in] regs Device's I/O registers range.
     140 * @param[in] regs Address of the memory mapped I/O registers.
     141 * @param[in] reg_size Size of the memory mapped area.
    260142 * @param[in] interrupts True if w interrupts should be used
    261143 * @return Error code
    262144 */
    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;
     145int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts)
     146{
     147        assert(instance);
     148
     149        int ret =
     150            pio_enable((void*)regs, reg_size, (void**)&instance->registers);
     151        if (ret != EOK) {
     152                usb_log_error("Failed to enable access to device regss: %s.\n",
     153                    str_error(ret));
     154                return ret;
    272155        }
    273156
    274157        list_initialize(&instance->pending_batches);
    275 
    276         hcd_init(&instance->generic, USB_SPEED_FULL,
    277             BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
    278         instance->generic.private_data = instance;
    279         instance->generic.schedule = hc_schedule;
    280         instance->generic.ep_add_hook = ohci_endpoint_init;
    281         instance->generic.ep_remove_hook = ohci_endpoint_fini;
    282 
    283         rc = hc_init_memory(instance);
    284         if (rc != EOK) {
     158        fibril_mutex_initialize(&instance->guard);
     159
     160        ret = hc_init_memory(instance);
     161        if (ret != EOK) {
    285162                usb_log_error("Failed to create OHCI memory structures: %s.\n",
    286                     str_error(rc));
    287                 return rc;
    288         }
    289 
    290         fibril_mutex_initialize(&instance->guard);
     163                    str_error(ret));
     164                return ret;
     165        }
    291166
    292167        hc_gain_control(instance);
     
    298173        }
    299174
    300         rh_init(&instance->rh, instance->registers);
     175        ohci_rh_init(&instance->rh, instance->registers, "ohci rh");
    301176        hc_start(instance);
    302177
     
    385260
    386261        /* Check for root hub communication */
    387         if (batch->ep->address == instance->rh.address) {
     262        if (batch->ep->address == ohci_rh_get_address(&instance->rh)) {
    388263                usb_log_debug("OHCI root hub request.\n");
    389                 rh_request(&instance->rh, batch);
    390                 return EOK;
     264                return ohci_rh_schedule(&instance->rh, batch);
    391265        }
    392266        ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch);
     
    427301        usb_log_debug2("OHCI(%p) interrupt: %x.\n", instance, status);
    428302        if (status & I_RHSC)
    429                 rh_interrupt(&instance->rh);
     303                ohci_rh_interrupt(&instance->rh);
    430304
    431305        if (status & I_WDH) {
     
    625499do { \
    626500        const char *name = usb_str_transfer_type(type); \
    627         int ret = endpoint_list_init(&instance->lists[type], name); \
     501        const int ret = endpoint_list_init(&instance->lists[type], name); \
    628502        if (ret != EOK) { \
    629503                usb_log_error("Failed to setup %s endpoint list: %s.\n", \
Note: See TracChangeset for help on using the changeset viewer.