Ignore:
File:
1 edited

Legend:

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

    r7de1988c rf5bfd98  
    3434 */
    3535
     36#include <assert.h>
     37#include <async.h>
    3638#include <errno.h>
    37 #include <stdbool.h>
     39#include <macros.h>
     40#include <mem.h>
     41#include <stdlib.h>
    3842#include <str_error.h>
    39 #include <adt/list.h>
    40 #include <libarch/ddi.h>
     43#include <sys/types.h>
    4144
    4245#include <usb/debug.h>
    4346#include <usb/usb.h>
    44 #include <usb/ddfiface.h>
     47
     48#include "ohci_endpoint.h"
     49#include "ohci_batch.h"
     50#include "utils/malloc32.h"
    4551
    4652#include "hc.h"
    47 #include "ohci_endpoint.h"
    4853
    4954#define OHCI_USED_INTERRUPTS \
     
    8489};
    8590
    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 
    9691static void hc_gain_control(hc_t *instance);
    9792static void hc_start(hc_t *instance);
     
    9994static int hc_init_memory(hc_t *instance);
    10095static int interrupt_emulator(hc_t *instance);
    101 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    10296
    10397/** Generate IRQ code.
     
    110104 * @return Error code.
    111105 */
    112 int
    113 hc_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)
    115 {
    116         if ((ranges_size < sizeof(ohci_pio_ranges)) ||
    117             (cmds_size < sizeof(ohci_irq_commands)) ||
    118             (RNGSZ(*regs) < sizeof(ohci_regs_t)))
     106int hc_gen_irq_code(irq_code_t *code, addr_range_t *regs)
     107{
     108        assert(code);
     109        if (RNGSZ(*regs) < sizeof(ohci_regs_t))
    119110                return EOVERFLOW;
    120111
    121         memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges));
    122         ranges[0].base = RNGABS(*regs);
    123 
    124         memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
     112        code->ranges = malloc(sizeof(ohci_pio_ranges));
     113        if (code->ranges == NULL)
     114                return ENOMEM;
     115
     116        code->cmds = malloc(sizeof(ohci_irq_commands));
     117        if (code->cmds == NULL) {
     118                free(code->ranges);
     119                return ENOMEM;
     120        }
     121
     122        code->rangecount = ARRAY_SIZE(ohci_pio_ranges);
     123        code->cmdcount = ARRAY_SIZE(ohci_irq_commands);
     124
     125        memcpy(code->ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges));
     126        code->ranges[0].base = RNGABS(*regs);
     127
     128        memcpy(code->cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
    125129        ohci_regs_t *registers = (ohci_regs_t *) RNGABSPTR(*regs);
    126         cmds[0].addr = (void *) &registers->interrupt_status;
    127         cmds[3].addr = (void *) &registers->interrupt_status;
    128         OHCI_WR(cmds[1].value, OHCI_USED_INTERRUPTS);
     130        code->cmds[0].addr = (void *) &registers->interrupt_status;
     131        code->cmds[3].addr = (void *) &registers->interrupt_status;
     132        OHCI_WR(code->cmds[1].value, OHCI_USED_INTERRUPTS);
    129133
    130134        return EOK;
    131 }
    132 
    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;
    254135}
    255136
     
    265146        assert(instance);
    266147
    267         int rc = pio_enable_range(regs, (void **) &instance->registers);
    268         if (rc != EOK) {
     148        int ret = pio_enable_range(regs, (void **) &instance->registers);
     149        if (ret != EOK) {
    269150                usb_log_error("Failed to gain access to device registers: %s.\n",
    270                     str_error(rc));
    271                 return rc;
     151                    str_error(ret));
     152                return ret;
    272153        }
    273154
    274155        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) {
     156        fibril_mutex_initialize(&instance->guard);
     157
     158        ret = hc_init_memory(instance);
     159        if (ret != EOK) {
    285160                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);
     161                    str_error(ret));
     162                return ret;
     163        }
    291164
    292165        hc_gain_control(instance);
     
    298171        }
    299172
    300         rh_init(&instance->rh, instance->registers);
     173        ohci_rh_init(&instance->rh, instance->registers, "ohci rh");
    301174        hc_start(instance);
    302175
     
    381254{
    382255        assert(hcd);
    383         hc_t *instance = hcd->private_data;
     256        hc_t *instance = hcd->driver.data;
    384257        assert(instance);
    385258
    386259        /* Check for root hub communication */
    387         if (batch->ep->address == instance->rh.address) {
     260        if (batch->ep->address == ohci_rh_get_address(&instance->rh)) {
    388261                usb_log_debug("OHCI root hub request.\n");
    389                 rh_request(&instance->rh, batch);
    390                 return EOK;
     262                return ohci_rh_schedule(&instance->rh, batch);
    391263        }
    392264        ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch);
     
    427299        usb_log_debug2("OHCI(%p) interrupt: %x.\n", instance, status);
    428300        if (status & I_RHSC)
    429                 rh_interrupt(&instance->rh);
     301                ohci_rh_interrupt(&instance->rh);
    430302
    431303        if (status & I_WDH) {
     
    512384                OHCI_SET(instance->registers->command_status, CS_OCR);
    513385                /* Hope that SMM actually knows its stuff or we can hang here */
    514                 while (OHCI_RD(instance->registers->control & C_IR)) {
     386                while (OHCI_RD(instance->registers->control) & C_IR) {
    515387                        async_usleep(1000);
    516388                }
     
    625497do { \
    626498        const char *name = usb_str_transfer_type(type); \
    627         int ret = endpoint_list_init(&instance->lists[type], name); \
     499        const int ret = endpoint_list_init(&instance->lists[type], name); \
    628500        if (ret != EOK) { \
    629501                usb_log_error("Failed to setup %s endpoint list: %s.\n", \
Note: See TracChangeset for help on using the changeset viewer.