Changeset b4b534ac in mainline for uspace/drv/bus/usb/ohci


Ignore:
Timestamp:
2016-07-22T08:24:47Z (10 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f76d2c2
Parents:
5b18137 (diff), 8351f9a4 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge from lp:~jan.vesely/helenos/usb

Location:
uspace/drv/bus/usb/ohci
Files:
1 added
4 deleted
18 edited
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ohci/Makefile

    r5b18137 rb4b534ac  
    3131LIBS = \
    3232        $(LIBUSBHOST_PREFIX)/libusbhost.a \
    33         $(LIBUSBDEV_PREFIX)/libusbdev.a \
     33        $(LIBUSBVIRT_PREFIX)/libusbvirt.a \
    3434        $(LIBUSB_PREFIX)/libusb.a \
    3535        $(LIBDRV_PREFIX)/libdrv.a
     
    3939        -I$(LIBUSBDEV_PREFIX)/include \
    4040        -I$(LIBUSBHOST_PREFIX)/include \
     41        -I$(LIBUSBVIRT_PREFIX)/include \
    4142        -I$(LIBDRV_PREFIX)/include
    4243
     
    4748        hc.c \
    4849        main.c \
    49         ohci.c \
    5050        ohci_batch.c \
    5151        ohci_endpoint.c \
    52         res.c \
    53         root_hub.c \
     52        ohci_rh.c \
    5453        hw_struct/endpoint_descriptor.c \
    5554        hw_struct/transfer_descriptor.c
  • uspace/drv/bus/usb/ohci/endpoint_list.c

    r5b18137 rb4b534ac  
    3434 */
    3535
     36#include <assert.h>
    3637#include <errno.h>
     38#include <libarch/barrier.h>
     39
    3740#include <usb/debug.h>
    38 #include <libarch/barrier.h>
     41#include <usb/host/utils/malloc32.h>
     42
    3943#include "endpoint_list.h"
    4044
  • uspace/drv/bus/usb/ohci/endpoint_list.h

    r5b18137 rb4b534ac  
    3535#define DRV_OHCI_ENDPOINT_LIST_H
    3636
     37#include <adt/list.h>
     38#include <assert.h>
    3739#include <fibril_synch.h>
     40#include <sys/types.h>
     41#include <usb/host/utils/malloc32.h>
    3842
    3943#include "ohci_endpoint.h"
    4044#include "hw_struct/endpoint_descriptor.h"
    41 #include "utils/malloc32.h"
    4245
    4346/** Structure maintains both OHCI queue and software list of active endpoints.*/
     
    6568        assert(instance);
    6669        free32(instance->list_head);
     70        instance->list_head = NULL;
    6771}
    6872
  • uspace/drv/bus/usb/ohci/hc.c

    r5b18137 rb4b534ac  
    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"
    4550
    4651#include "hc.h"
    47 #include "ohci_endpoint.h"
    4852
    4953#define OHCI_USED_INTERRUPTS \
     
    8488};
    8589
    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 
    9690static void hc_gain_control(hc_t *instance);
    9791static void hc_start(hc_t *instance);
    9892static int hc_init_transfer_lists(hc_t *instance);
    9993static int hc_init_memory(hc_t *instance);
    100 static int interrupt_emulator(hc_t *instance);
    101 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    10294
    10395/** Generate IRQ code.
     
    10698 * @param[out] cmds Commands buffer.
    10799 * @param[in] cmds_size Size of the commands buffer (bytes).
    108  * @param[in] regs Device's register range.
     100 * @param[in] hw_res Device's resources.
    109101 *
    110102 * @return Error code.
    111103 */
    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)))
     104int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)
     105{
     106        assert(code);
     107        assert(hw_res);
     108
     109        if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1)
     110                return EINVAL;
     111
     112        const addr_range_t regs = hw_res->mem_ranges.ranges[0];
     113
     114        if (RNGSZ(regs) < sizeof(ohci_regs_t))
    119115                return EOVERFLOW;
    120116
    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));
    125         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);
    129 
    130         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;
     117        code->ranges = malloc(sizeof(ohci_pio_ranges));
     118        if (code->ranges == NULL)
     119                return ENOMEM;
     120
     121        code->cmds = malloc(sizeof(ohci_irq_commands));
     122        if (code->cmds == NULL) {
     123                free(code->ranges);
     124                return ENOMEM;
     125        }
     126
     127        code->rangecount = ARRAY_SIZE(ohci_pio_ranges);
     128        code->cmdcount = ARRAY_SIZE(ohci_irq_commands);
     129
     130        memcpy(code->ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges));
     131        code->ranges[0].base = RNGABS(regs);
     132
     133        memcpy(code->cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
     134        ohci_regs_t *registers = (ohci_regs_t *) RNGABSPTR(regs);
     135        code->cmds[0].addr = (void *) &registers->interrupt_status;
     136        code->cmds[3].addr = (void *) &registers->interrupt_status;
     137        OHCI_WR(code->cmds[1].value, OHCI_USED_INTERRUPTS);
     138
     139        usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
     140            RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]);
     141
     142        return hw_res->irqs.irqs[0];
    254143}
    255144
     
    257146 *
    258147 * @param[in] instance Memory place for the structure.
    259  * @param[in] HC function node
    260  * @param[in] regs Device's I/O registers range.
     148 * @param[in] regs Device's resources
    261149 * @param[in] interrupts True if w interrupts should be used
    262150 * @return Error code
    263151 */
    264 int hc_init(hc_t *instance, ddf_fun_t *fun, addr_range_t *regs, bool interrupts)
    265 {
    266         assert(instance);
    267 
    268         int rc = pio_enable_range(regs, (void **) &instance->registers);
    269         if (rc != EOK) {
    270                 usb_log_error("Failed to gain access to device registers: %s.\n",
    271                     str_error(rc));
    272                 return rc;
    273         }
     152int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
     153{
     154        assert(instance);
     155        assert(hw_res);
     156        if (hw_res->mem_ranges.count != 1 ||
     157            hw_res->mem_ranges.ranges[0].size < sizeof(ohci_regs_t))
     158            return EINVAL;
     159
     160        int ret = pio_enable_range(&hw_res->mem_ranges.ranges[0],
     161            (void **) &instance->registers);
     162        if (ret != EOK) {
     163                usb_log_error("Failed to gain access to registers: %s.\n",
     164                    str_error(ret));
     165                return ret;
     166        }
     167        usb_log_debug("Device registers at %" PRIx64 " (%zuB) accessible.\n",
     168            hw_res->mem_ranges.ranges[0].address.absolute,
     169            hw_res->mem_ranges.ranges[0].size);
    274170
    275171        list_initialize(&instance->pending_batches);
    276 
    277         instance->generic = ddf_fun_data_alloc(fun, sizeof(hcd_t));
    278         if (instance->generic == NULL) {
    279                 usb_log_error("Out of memory.\n");
    280                 return ENOMEM;
    281         }
    282 
    283         hcd_init(instance->generic, USB_SPEED_FULL,
    284             BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
    285         instance->generic->private_data = instance;
    286         instance->generic->schedule = hc_schedule;
    287         instance->generic->ep_add_hook = ohci_endpoint_init;
    288         instance->generic->ep_remove_hook = ohci_endpoint_fini;
    289 
    290         rc = hc_init_memory(instance);
    291         if (rc != EOK) {
     172        fibril_mutex_initialize(&instance->guard);
     173        instance->hw_interrupts = interrupts;
     174
     175        ret = hc_init_memory(instance);
     176        if (ret != EOK) {
    292177                usb_log_error("Failed to create OHCI memory structures: %s.\n",
    293                     str_error(rc));
    294                 return rc;
    295         }
    296 
    297         fibril_mutex_initialize(&instance->guard);
     178                    str_error(ret));
     179                //TODO: We should disable pio access here
     180                return ret;
     181        }
    298182
    299183        hc_gain_control(instance);
    300184
    301         if (!interrupts) {
    302                 instance->interrupt_emulator =
    303                     fibril_create((int(*)(void*))interrupt_emulator, instance);
    304                 fibril_add_ready(instance->interrupt_emulator);
    305         }
    306 
    307         rh_init(&instance->rh, instance->registers);
     185        ohci_rh_init(&instance->rh, instance->registers, "ohci rh");
    308186        hc_start(instance);
    309187
    310188        return EOK;
    311189}
     190
     191/** Safely dispose host controller internal structures
     192 *
     193 * @param[in] instance Host controller structure to use.
     194 */
     195void hc_fini(hc_t *instance)
     196{
     197        assert(instance);
     198        /* TODO: implement*/
     199};
    312200
    313201void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep)
     
    379267}
    380268
     269int ohci_hc_status(hcd_t *hcd, uint32_t *status)
     270{
     271        assert(hcd);
     272        assert(status);
     273        hc_t *instance = hcd_get_driver_data(hcd);
     274        assert(instance);
     275
     276        if (instance->registers){
     277                *status = OHCI_RD(instance->registers->interrupt_status);
     278                OHCI_WR(instance->registers->interrupt_status, *status);
     279        }
     280        return EOK;
     281}
     282
    381283/** Add USB transfer to the schedule.
    382284 *
    383  * @param[in] instance OHCI hc driver structure.
     285 * @param[in] hcd HCD driver structure.
    384286 * @param[in] batch Batch representing the transfer.
    385287 * @return Error code.
    386288 */
    387 int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
     289int ohci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
    388290{
    389291        assert(hcd);
    390         hc_t *instance = hcd->private_data;
     292        hc_t *instance = hcd_get_driver_data(hcd);
    391293        assert(instance);
    392294
    393295        /* Check for root hub communication */
    394         if (batch->ep->address == instance->rh.address) {
     296        if (batch->ep->address == ohci_rh_get_address(&instance->rh)) {
    395297                usb_log_debug("OHCI root hub request.\n");
    396                 rh_request(&instance->rh, batch);
    397                 return EOK;
     298                return ohci_rh_schedule(&instance->rh, batch);
    398299        }
    399300        ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch);
     
    423324/** Interrupt handling routine
    424325 *
    425  * @param[in] instance OHCI hc driver structure.
     326 * @param[in] hcd HCD driver structure.
    426327 * @param[in] status Value of the status register at the time of interrupt.
    427328 */
    428 void hc_interrupt(hc_t *instance, uint32_t status)
    429 {
     329void ohci_hc_interrupt(hcd_t *hcd, uint32_t status)
     330{
     331        assert(hcd);
     332        hc_t *instance = hcd_get_driver_data(hcd);
    430333        status = OHCI_RD(status);
    431334        assert(instance);
     
    434337        usb_log_debug2("OHCI(%p) interrupt: %x.\n", instance, status);
    435338        if (status & I_RHSC)
    436                 rh_interrupt(&instance->rh);
     339                ohci_rh_interrupt(&instance->rh);
    437340
    438341        if (status & I_WDH) {
     
    465368        }
    466369
    467 }
    468 
    469 /** Check status register regularly
    470  *
    471  * @param[in] instance OHCI hc driver structure.
    472  * @return Error code
    473  */
    474 int interrupt_emulator(hc_t *instance)
    475 {
    476         assert(instance);
    477         usb_log_info("Started interrupt emulator.\n");
    478         while (1) {
    479                 const uint32_t status = instance->registers->interrupt_status;
    480                 instance->registers->interrupt_status = status;
    481                 hc_interrupt(instance, status);
    482                 async_usleep(10000);
    483         }
    484         return EOK;
    485370}
    486371
     
    508393                    ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
    509394                /* Zero everything but A20State */
     395                //TODO: should we ack interrupts before doing this?
    510396                OHCI_CLR(*ohci_emulation_reg, ~0x100);
    511397                usb_log_debug(
     
    517403        if (OHCI_RD(instance->registers->control) & C_IR) {
    518404                usb_log_debug("SMM driver: request ownership change.\n");
     405                //TODO: should we ack interrupts before doing this?
    519406                OHCI_SET(instance->registers->command_status, CS_OCR);
    520407                /* Hope that SMM actually knows its stuff or we can hang here */
    521                 while (OHCI_RD(instance->registers->control & C_IR)) {
     408                while (OHCI_RD(instance->registers->control) & C_IR) {
    522409                        async_usleep(1000);
    523410                }
     
    603490
    604491        /* Enable interrupts */
    605         OHCI_WR(instance->registers->interrupt_enable, OHCI_USED_INTERRUPTS);
    606         usb_log_debug("Enabled interrupts: %x.\n",
    607             OHCI_RD(instance->registers->interrupt_enable));
    608         OHCI_WR(instance->registers->interrupt_enable, I_MI);
     492        if (instance->hw_interrupts) {
     493                OHCI_WR(instance->registers->interrupt_enable,
     494                    OHCI_USED_INTERRUPTS);
     495                usb_log_debug("Enabled interrupts: %x.\n",
     496                    OHCI_RD(instance->registers->interrupt_enable));
     497                OHCI_WR(instance->registers->interrupt_enable, I_MI);
     498        }
    609499
    610500        /* Set periodic start to 90% */
     
    632522do { \
    633523        const char *name = usb_str_transfer_type(type); \
    634         int ret = endpoint_list_init(&instance->lists[type], name); \
     524        const int ret = endpoint_list_init(&instance->lists[type], name); \
    635525        if (ret != EOK) { \
    636526                usb_log_error("Failed to setup %s endpoint list: %s.\n", \
  • uspace/drv/bus/usb/ohci/hc.h

    r5b18137 rb4b534ac  
    3535#define DRV_OHCI_HC_H
    3636
     37#include <adt/list.h>
     38#include <ddi.h>
    3739#include <ddf/driver.h>
    38 #include <ddf/interrupt.h>
     40#include <device/hw_res_parsed.h>
    3941#include <fibril.h>
    4042#include <fibril_synch.h>
    41 #include <adt/list.h>
    42 #include <ddi.h>
     43#include <stdbool.h>
     44#include <sys/types.h>
    4345
    44 #include <usb/usb.h>
    4546#include <usb/host/hcd.h>
     47#include <usb/host/endpoint.h>
     48#include <usb/host/usb_transfer_batch.h>
    4649
    47 #include "ohci_batch.h"
    4850#include "ohci_regs.h"
    49 #include "root_hub.h"
     51#include "ohci_rh.h"
    5052#include "endpoint_list.h"
    5153#include "hw_struct/hcca.h"
     
    5355/** Main OHCI driver structure */
    5456typedef struct hc {
    55         /** Generic USB hc driver */
    56         hcd_t *generic;
    57 
    5857        /** Memory mapped I/O registers area */
    5958        ohci_regs_t *registers;
     
    7271        fibril_mutex_t guard;
    7372
     73        /** interrupts available */
     74        bool hw_interrupts;
     75
    7476        /** USB hub emulation structure */
    75         rh_t rh;
     77        ohci_rh_t rh;
    7678} hc_t;
    7779
    78 int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t,
    79     addr_range_t *);
    80 int hc_register_irq_handler(ddf_dev_t *, addr_range_t *, int,
    81     interrupt_handler_t);
    82 int hc_register_hub(hc_t *, ddf_fun_t *);
    83 int hc_init(hc_t *, ddf_fun_t *, addr_range_t *, bool);
    84 
    85 /** Safely dispose host controller internal structures
    86  *
    87  * @param[in] instance Host controller structure to use.
    88  */
    89 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
     80int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts);
     81void hc_fini(hc_t *instance);
    9082
    9183void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep);
    9284void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep);
    9385
    94 void hc_interrupt(hc_t *instance, uint32_t status);
     86int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res);
     87
     88void ohci_hc_interrupt(hcd_t *hcd, uint32_t status);
     89int ohci_hc_status(hcd_t *hcd, uint32_t *status);
     90int ohci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    9591#endif
    9692/**
  • uspace/drv/bus/usb/ohci/hw_struct/completion_codes.h

    r5b18137 rb4b534ac  
    3737#include <errno.h>
    3838
    39 #define CC_NOERROR (0x0)
    40 #define CC_CRC (0x1)
    41 #define CC_BITSTUFF (0x2)
    42 #define CC_TOGGLE (0x3)
    43 #define CC_STALL (0x4)
    44 #define CC_NORESPONSE (0x5)
    45 #define CC_PIDFAIL (0x6)
    46 #define CC_PIDUNEXPECTED (0x7)
    47 #define CC_DATAOVERRRUN (0x8)
    48 #define CC_DATAUNDERRRUN (0x9)
    49 #define CC_BUFFEROVERRRUN (0xc)
    50 #define CC_BUFFERUNDERRUN (0xd)
    51 #define CC_NOACCESS1 (0xe)
    52 #define CC_NOACCESS2 (0xf)
     39enum {
     40        CC_NOERROR = 0x0,
     41        CC_CRC = 0x1,
     42        CC_BITSTUFF = 0x2,
     43        CC_TOGGLE = 0x3,
     44        CC_STALL = 0x4,
     45        CC_NORESPONSE = 0x5,
     46        CC_PIDFAIL = 0x6,
     47        CC_PIDUNEXPECTED = 0x7,
     48        CC_DATAOVERRRUN = 0x8,
     49        CC_DATAUNDERRRUN = 0x9,
     50        CC_BUFFEROVERRRUN = 0xc,
     51        CC_BUFFERUNDERRUN = 0xd,
     52        CC_NOACCESS1 = 0xe,
     53        CC_NOACCESS2 = 0xf,
     54};
    5355
    54 inline static int cc_to_rc(int cc)
     56inline static unsigned cc_to_rc(unsigned cc)
    5557{
    5658        switch (cc) {
  • uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c

    r5b18137 rb4b534ac  
    3232 * @brief OHCI driver
    3333 */
     34
     35#include <assert.h>
     36#include <macros.h>
     37#include <mem.h>
     38
     39#include <usb/usb.h>
     40#include <usb/host/utils/malloc32.h>
     41
     42#include "mem_access.h"
     43
    3444#include "endpoint_descriptor.h"
    3545
     
    4858 * @param td TD to put in the list.
    4959 *
    50  * If @param ep is NULL, dummy ED is initalized with only skip flag set.
     60 * If @param ep is NULL, dummy ED is initialized with only skip flag set.
    5161 */
    5262void ed_init(ed_t *instance, const endpoint_t *ep, const td_t *td)
    5363{
    5464        assert(instance);
    55         memset(instance, 0, sizeof(ed_t));
     65        memset(instance, 0, sizeof(*instance));
    5666
    5767        if (ep == NULL) {
     
    6171                return;
    6272        }
    63         /* Non-dummy ED must have TD assigned */
     73        /* Non-dummy ED must have corresponding EP and TD assigned */
    6474        assert(td);
     75        assert(ep);
     76        assert(ep->direction < ARRAY_SIZE(dir));
    6577
    6678        /* Status: address, endpoint nr, direction mask and max packet size. */
     
    7789
    7890        /* Isochronous format flag */
     91        // TODO: We need iTD instead of TD for iso transfers
    7992        if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS)
    8093                OHCI_MEM32_SET(instance->status, ED_STATUS_F_FLAG);
  • uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h

    r5b18137 rb4b534ac  
    3636
    3737#include <assert.h>
    38 #include <stdint.h>
     38#include <stdbool.h>
     39#include <sys/types.h>
    3940
    4041#include <usb/host/endpoint.h>
    41 
    42 #include "../utils/malloc32.h"
     42#include <usb/host/utils/malloc32.h>
     43
    4344#include "transfer_descriptor.h"
    4445
  • uspace/drv/bus/usb/ohci/hw_struct/hcca.h

    r5b18137 rb4b534ac  
    3535#define DRV_OHCI_HW_STRUCT_HCCA_H
    3636
    37 #include <stdint.h>
    3837#include <malloc.h>
     38#include <sys/types.h>
     39#include <macros.h>
    3940
    4041#include "mem_access.h"
     
    5051        /** Frame number. */
    5152        uint16_t frame_number;
    52         uint16_t pad1;
     53        PADD16;
    5354        /** Pointer to the last completed TD. (useless) */
    5455        uint32_t done_head;
    5556        /** Padding to make the size 256B */
    56         uint32_t reserved[30];
     57        PADD32[30];
    5758} hcca_t;
     59
     60STATIC_ASSERT(sizeof(hcca_t) == 256);
    5861
    5962/** Allocate properly aligned structure.
     
    6568static inline hcca_t * hcca_get(void)
    6669{
    67         static_assert(sizeof(hcca_t) == 256);
    68         hcca_t *hcca = memalign(256, sizeof(hcca_t));
     70        hcca_t *hcca = memalign(sizeof(hcca_t), sizeof(hcca_t));
    6971        if (hcca)
    7072                memset(hcca, 0, sizeof(hcca_t));
     
    8082{
    8183        assert(hcca);
    82         assert(index < HCCA_INT_EP_COUNT);
     84        assert(index < ARRAY_SIZE(hcca->int_ep));
    8385        OHCI_MEM32_WR(hcca->int_ep[index], pa);
    84 
    8586}
    8687#endif
  • uspace/drv/bus/usb/ohci/hw_struct/iso_transfer_descriptor.h

    r5b18137 rb4b534ac  
    3535#define DRV_OHCI_HW_STRUCT_ISO_TRANSFER_DESCRIPTOR_H
    3636
    37 #include <stdint.h>
     37#include <sys/types.h>
    3838
    3939#include "completion_codes.h"
  • uspace/drv/bus/usb/ohci/hw_struct/mem_access.h

    r5b18137 rb4b534ac  
    4747 * @}
    4848 */
    49 
  • uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c

    r5b18137 rb4b534ac  
    3232 * @brief OHCI driver
    3333 */
     34
     35#include <assert.h>
     36#include <mem.h>
     37
    3438#include <usb/usb.h>
    35 #include <mem.h>
    36 #include "../utils/malloc32.h"
     39#include <usb/host/utils/malloc32.h>
     40
     41#include "completion_codes.h"
     42#include "mem_access.h"
    3743#include "transfer_descriptor.h"
    3844
     
    7076        }
    7177
    72         /* Alow less data on input. */
     78        /* Allow less data on input. */
    7379        if (dir == USB_DIRECTION_IN) {
    7480                OHCI_MEM32_SET(instance->status, TD_STATUS_ROUND_FLAG);
  • uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h

    r5b18137 rb4b534ac  
    3535#define DRV_OHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
    3636
     37#include <assert.h>
    3738#include <stdbool.h>
    3839#include <stdint.h>
  • uspace/drv/bus/usb/ohci/main.c

    r5b18137 rb4b534ac  
    3333 * Main routines of OHCI driver.
    3434 */
     35
     36#include <assert.h>
    3537#include <ddf/driver.h>
    3638#include <errno.h>
     39#include <io/log.h>
    3740#include <str_error.h>
    3841
    3942#include <usb/debug.h>
     43#include <usb/host/ddf_helpers.h>
    4044
    41 #include "ohci.h"
     45#include "hc.h"
    4246
    4347#define NAME "ohci"
     48static int ohci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool);
     49static void ohci_driver_fini(hcd_t *);
     50
     51static const ddf_hc_driver_t ohci_hc_driver = {
     52        .hc_speed = USB_SPEED_FULL,
     53        .irq_code_gen = ohci_hc_gen_irq_code,
     54        .init = ohci_driver_init,
     55        .fini = ohci_driver_fini,
     56        .name = "OHCI",
     57        .ops = {
     58                .schedule       = ohci_hc_schedule,
     59                .ep_add_hook    = ohci_endpoint_init,
     60                .ep_remove_hook = ohci_endpoint_fini,
     61                .irq_hook       = ohci_hc_interrupt,
     62                .status_hook    = ohci_hc_status,
     63        },
     64};
     65
     66
     67static int ohci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, bool irq)
     68{
     69        assert(hcd);
     70        assert(hcd_get_driver_data(hcd) == NULL);
     71
     72        hc_t *instance = malloc(sizeof(hc_t));
     73        if (!instance)
     74                return ENOMEM;
     75
     76        const int ret = hc_init(instance, res, irq);
     77        if (ret == EOK) {
     78                hcd_set_implementation(hcd, instance, &ohci_hc_driver.ops);
     79        } else {
     80                free(instance);
     81        }
     82        return ret;
     83}
     84
     85static void ohci_driver_fini(hcd_t *hcd)
     86{
     87        assert(hcd);
     88        hc_t *hc = hcd_get_driver_data(hcd);
     89        if (hc)
     90                hc_fini(hc);
     91
     92        hcd_set_implementation(hcd, NULL, NULL);
     93        free(hc);
     94}
    4495
    4596/** Initializes a new ddf driver instance of OHCI hcd.
     
    52103        usb_log_debug("ohci_dev_add() called\n");
    53104        assert(device);
    54 
    55         int ret = device_setup_ohci(device);
    56         if (ret != EOK) {
    57                 usb_log_error("Failed to initialize OHCI driver: %s.\n",
    58                     str_error(ret));
    59                 return ret;
    60         }
    61         usb_log_info("Controlling new OHCI device '%s'.\n", ddf_dev_get_name(device));
    62 
    63         return EOK;
     105        return hcd_ddf_add_hc(device, &ohci_hc_driver);
    64106}
    65107
    66 static driver_ops_t ohci_driver_ops = {
     108static const driver_ops_t ohci_driver_ops = {
    67109        .dev_add = ohci_dev_add,
    68110};
    69111
    70 static driver_t ohci_driver = {
     112static const driver_t ohci_driver = {
    71113        .name = NAME,
    72114        .driver_ops = &ohci_driver_ops
  • uspace/drv/bus/usb/ohci/ohci_batch.c

    r5b18137 rb4b534ac  
    3232 * @brief OHCI driver USB transaction structure
    3333 */
     34
     35#include <assert.h>
    3436#include <errno.h>
    35 #include <str_error.h>
    3637#include <macros.h>
     38#include <mem.h>
     39#include <stdbool.h>
    3740
    3841#include <usb/usb.h>
    3942#include <usb/debug.h>
     43#include <usb/host/utils/malloc32.h>
    4044
    4145#include "ohci_batch.h"
    4246#include "ohci_endpoint.h"
    43 #include "utils/malloc32.h"
    4447
    4548static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t);
     
    9497{
    9598        assert(usb_batch);
    96 #define CHECK_NULL_DISPOSE_RET(ptr, message...) \
    97 if (ptr == NULL) { \
    98         usb_log_error(message); \
    99         ohci_transfer_batch_dispose(ohci_batch); \
    100         return NULL; \
    101 } else (void)0
    10299
    103100        ohci_transfer_batch_t *ohci_batch =
    104101            calloc(1, sizeof(ohci_transfer_batch_t));
    105         CHECK_NULL_DISPOSE_RET(ohci_batch,
    106             "Failed to allocate OHCI batch data.\n");
     102        if (!ohci_batch) {
     103                usb_log_error("Failed to allocate OHCI batch data.");
     104                goto dispose;
     105        }
    107106        link_initialize(&ohci_batch->link);
    108107        ohci_batch->td_count =
     
    116115        /* We need an extra place for TD that was left at ED */
    117116        ohci_batch->tds = calloc(ohci_batch->td_count + 1, sizeof(td_t*));
    118         CHECK_NULL_DISPOSE_RET(ohci_batch->tds,
    119             "Failed to allocate OHCI transfer descriptors.\n");
     117        if (!ohci_batch->tds) {
     118                usb_log_error("Failed to allocate OHCI transfer descriptors.");
     119                goto dispose;
     120        }
    120121
    121122        /* Add TD left over by the previous transfer */
     
    125126        for (unsigned i = 1; i <= ohci_batch->td_count; ++i) {
    126127                ohci_batch->tds[i] = malloc32(sizeof(td_t));
    127                 CHECK_NULL_DISPOSE_RET(ohci_batch->tds[i],
    128                     "Failed to allocate TD %d.\n", i );
     128                if (!ohci_batch->tds[i]) {
     129                        usb_log_error("Failed to allocate TD %d.", i);
     130                        goto dispose;
     131                }
    129132        }
    130133
     
    138141                ohci_batch->device_buffer =
    139142                    malloc32(usb_batch->setup_size + usb_batch->buffer_size);
    140                 CHECK_NULL_DISPOSE_RET(ohci_batch->device_buffer,
    141                     "Failed to allocate device accessible buffer.\n");
     143                if (!ohci_batch->device_buffer) {
     144                        usb_log_error("Failed to allocate device buffer");
     145                        goto dispose;
     146                }
    142147                /* Copy setup data */
    143148                memcpy(ohci_batch->device_buffer, usb_batch->setup_buffer,
     
    156161
    157162        return ohci_batch;
    158 #undef CHECK_NULL_DISPOSE_RET
     163dispose:
     164        ohci_transfer_batch_dispose(ohci_batch);
     165        return NULL;
    159166}
    160167
  • uspace/drv/bus/usb/ohci/ohci_batch.h

    r5b18137 rb4b534ac  
    3636
    3737#include <adt/list.h>
    38 #include <usbhc_iface.h>
    39 #include <usb/usb.h>
     38#include <assert.h>
     39#include <stdbool.h>
    4040#include <usb/host/usb_transfer_batch.h>
    4141
  • uspace/drv/bus/usb/ohci/ohci_endpoint.c

    r5b18137 rb4b534ac  
    3232 * @brief OHCI driver
    3333 */
    34 #include "utils/malloc32.h"
     34
     35#include <assert.h>
     36#include <stdlib.h>
     37#include <usb/host/utils/malloc32.h>
     38
    3539#include "ohci_endpoint.h"
    3640#include "hc.h"
     
    8791        }
    8892
     93        link_initialize(&ohci_ep->link);
    8994        ed_init(ohci_ep->ed, ep, ohci_ep->td);
    9095        endpoint_set_hc_data(
    9196            ep, ohci_ep, ohci_ep_toggle_get, ohci_ep_toggle_set);
    92         hc_enqueue_endpoint(hcd->private_data, ep);
     97        hc_enqueue_endpoint(hcd_get_driver_data(hcd), ep);
    9398        return EOK;
    9499}
     
    104109        assert(ep);
    105110        ohci_endpoint_t *instance = ohci_endpoint_get(ep);
    106         hc_dequeue_endpoint(hcd->private_data, ep);
     111        hc_dequeue_endpoint(hcd_get_driver_data(hcd), ep);
     112        endpoint_clear_hc_data(ep);
    107113        if (instance) {
    108114                free32(instance->ed);
     
    110116                free(instance);
    111117        }
    112         endpoint_clear_hc_data(ep);
    113118}
    114119/**
  • uspace/drv/bus/usb/ohci/ohci_regs.h

    r5b18137 rb4b534ac  
    3434#ifndef DRV_OHCI_OHCI_REGS_H
    3535#define DRV_OHCI_OHCI_REGS_H
     36#include <ddi.h>
    3637#include <sys/types.h>
    3738#include <byteorder.h>
    3839
    39 #define OHCI_WR(reg, val) reg = host2uint32_t_le(val)
    40 #define OHCI_RD(reg) uint32_t_le2host(reg)
    41 #define OHCI_SET(reg, val) reg |= host2uint32_t_le(val)
    42 #define OHCI_CLR(reg, val) reg &= host2uint32_t_le(~val)
    43 
     40#define OHCI_WR(reg, val) pio_write_32(&(reg), host2uint32_t_le(val))
     41#define OHCI_RD(reg) uint32_t_le2host(pio_read_32(&(reg)))
     42#define OHCI_SET(reg, val) pio_set_32(&(reg), host2uint32_t_le(val), 1)
     43#define OHCI_CLR(reg, val) pio_clear_32(&(reg), host2uint32_t_le(val), 1)
    4444
    4545#define LEGACY_REGS_OFFSET 0x100
     
    215215        /** Root hub per port status */
    216216        ioport32_t rh_port_status[];
    217 #define RHPS_CCS_FLAG (1 << 0) /* r: current connect status,
     217#define RHPS_CCS_FLAG (1 << 0)                /* r: current connect status,
    218218                                               * w: 1-clear port enable, 0-N/S*/
    219219#define RHPS_CLEAR_PORT_ENABLE RHPS_CCS_FLAG
    220 #define RHPS_PES_FLAG (1 << 1) /* r: port enable status
     220#define RHPS_PES_FLAG (1 << 1)               /* r: port enable status
    221221                                              * w: 1-set port enable, 0-N/S */
    222222#define RHPS_SET_PORT_ENABLE RHPS_PES_FLAG
    223 #define RHPS_PSS_FLAG (1 << 2) /* r: port suspend status
     223#define RHPS_PSS_FLAG (1 << 2)                /* r: port suspend status
    224224                                               * w: 1-set port suspend, 0-N/S */
    225225#define RHPS_SET_PORT_SUSPEND RHPS_PSS_FLAG
    226 #define RHPS_POCI_FLAG (1 << 3) /* r: port over-current
     226#define RHPS_POCI_FLAG (1 << 3)                /* r: port over-current
    227227                                                * (if reports are per-port
    228228                                                * w: 1-clear port suspend
     
    230230                                                *    0-nothing */
    231231#define RHPS_CLEAR_PORT_SUSPEND RHPS_POCI_FLAG
    232 #define RHPS_PRS_FLAG (1 << 4) /* r: port reset status
     232#define RHPS_PRS_FLAG (1 << 4)                /* r: port reset status
    233233                                               * w: 1-set port reset, 0-N/S */
    234234#define RHPS_SET_PORT_RESET RHPS_PRS_FLAG
    235 #define RHPS_PPS_FLAG (1 << 8) /* r: port power status
     235#define RHPS_PPS_FLAG (1 << 8)               /* r: port power status
    236236                                              * w: 1-set port power, 0-N/S */
    237237#define RHPS_SET_PORT_POWER RHPS_PPS_FLAG
    238 #define RHPS_LSDA_FLAG (1 << 9) /* r: low speed device attached
     238#define RHPS_LSDA_FLAG (1 << 9)                /* r: low speed device attached
    239239                                                * w: 1-clear port power, 0-N/S*/
    240240#define RHPS_CLEAR_PORT_POWER RHPS_LSDA_FLAG
  • uspace/drv/bus/usb/ohci/ohci_rh.h

    r5b18137 rb4b534ac  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2013 Jan Vesely
    33 * All rights reserved.
    44 *
     
    3232 * @brief OHCI driver
    3333 */
    34 #ifndef DRV_OHCI_ROOT_HUB_H
    35 #define DRV_OHCI_ROOT_HUB_H
     34#ifndef DRV_OHCI_OHCI_RH_H
     35#define DRV_OHCI_OHCI_RH_H
     36
     37#include <assert.h>
     38#include <sys/types.h>
    3639
    3740#include <usb/usb.h>
    38 #include <usb/dev/driver.h>
     41#include <usb/classes/hub.h>
    3942#include <usb/host/usb_transfer_batch.h>
     43#include <usbvirt/virthub_base.h>
    4044
    4145#include "ohci_regs.h"
    4246
    43 #define HUB_DESCRIPTOR_MAX_SIZE (7 + 2 + 2)
     47enum {
     48        OHCI_MAX_PORTS = 15,
     49};
    4450
    45 /**
    46  * ohci root hub representation
    47  */
    48 typedef struct rh {
    49         fibril_mutex_t guard;
    50         /** pointer to ohci driver registers */
     51typedef struct {
     52        /** Virtual hub instance */
     53        virthub_base_t base;
     54        /** OHCI device registers */
    5155        ohci_regs_t *registers;
    52         /** usb address of the root hub */
    53         usb_address_t address;
    54         /** hub port count */
    55         size_t port_count;
     56        /** Number of downstream ports, OHCI limits this to 15 */
     57        unsigned port_count;
     58        /** USB hub descriptor describing the OHCI root hub */
     59        struct {
     60                usb_hub_descriptor_header_t header;
     61                uint8_t rempow[STATUS_BYTES(OHCI_MAX_PORTS) * 2];
     62        } __attribute__((packed)) hub_descriptor;
    5663        /** interrupt transfer waiting for an actual interrupt to occur */
    5764        usb_transfer_batch_t *unfinished_interrupt_transfer;
    58         /** size of interrupt buffer */
    59         size_t interrupt_mask_size;
    60         /** Descriptors */
    61         struct {
    62                 usb_standard_configuration_descriptor_t configuration;
    63                 usb_standard_interface_descriptor_t interface;
    64                 usb_standard_endpoint_descriptor_t endpoint;
    65                 uint8_t hub[HUB_DESCRIPTOR_MAX_SIZE];
    66         } __attribute__ ((packed)) descriptors;
    67         /** size of hub descriptor */
    68         size_t hub_descriptor_size;
    69 } rh_t;
     65} ohci_rh_t;
    7066
    71 void rh_init(rh_t *instance, ohci_regs_t *regs);
     67int ohci_rh_init(ohci_rh_t *instance, ohci_regs_t *regs, const char *name);
     68int ohci_rh_schedule(ohci_rh_t *instance, usb_transfer_batch_t *batch);
     69int ohci_rh_interrupt(ohci_rh_t *instance);
    7270
    73 void rh_request(rh_t *instance, usb_transfer_batch_t *request);
    74 
    75 void rh_interrupt(rh_t *instance);
     71/** Get OHCI rh address.
     72 *
     73 * @param instance UHCI rh instance.
     74 * @return USB address assigned to the hub.
     75 * Wrapper for virtual hub address
     76 */
     77static inline usb_address_t ohci_rh_get_address(ohci_rh_t *instance)
     78{
     79        assert(instance);
     80        return virthub_base_get_address(&instance->base);
     81}
    7682#endif
    7783/**
Note: See TracChangeset for help on using the changeset viewer.