Changes in / [f1d6866:85ff862] in mainline


Ignore:
Files:
15 added
16 deleted
60 edited

Legend:

Unmodified
Added
Removed
  • boot/Makefile.common

    rf1d6866 r85ff862  
    166166        $(USPACE_PATH)/app/lsusb/lsusb \
    167167        $(USPACE_PATH)/app/sbi/sbi \
    168         $(USPACE_PATH)/app/sportdmp/sportdmp \
    169168        $(USPACE_PATH)/app/redir/redir \
    170169        $(USPACE_PATH)/app/taskdump/taskdump \
  • kernel/arch/arm32/src/ras.c

    rf1d6866 r85ff862  
    8686}
    8787
    88 /** @}
    89  */
  • kernel/generic/include/adt/list.h

    rf1d6866 r85ff862  
    173173 *
    174174 */
    175 NO_TRACE static inline int list_empty(const list_t *list)
     175NO_TRACE static inline int list_empty(list_t *list)
    176176{
    177177        return (list->head.next == &list->head);
     
    186186 *
    187187 */
    188 static inline link_t *list_first(const list_t *list)
     188static inline link_t *list_first(list_t *list)
    189189{
    190190        return ((list->head.next == &list->head) ? NULL : list->head.next);
  • kernel/generic/src/mm/frame.c

    rf1d6866 r85ff862  
    11421142        size_t znum = find_zone(pfn, 1, 0);
    11431143
     1144       
    11441145        ASSERT(znum != (size_t) -1);
    11451146       
  • uspace/Makefile

    rf1d6866 r85ff862  
    5151        app/redir \
    5252        app/sbi \
    53         app/sportdmp \
    5453        app/stats \
    5554        app/taskdump \
  • uspace/drv/bus/isa/isa.c

    rf1d6866 r85ff862  
    405405static void fun_hw_res_alloc(isa_fun_t *fun)
    406406{
    407         fun->hw_resources.resources =
     407        fun->hw_resources.resources = 
    408408            (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
    409409}
  • uspace/drv/bus/usb/ehci/hc_iface.c

    rf1d6866 r85ff862  
    145145}
    146146
     147/** Schedule interrupt out transfer.
     148 *
     149 * The callback is supposed to be called once the transfer (on the wire) is
     150 * complete regardless of the outcome.
     151 * However, the callback could be called only when this function returns
     152 * with success status (i.e. returns EOK).
     153 *
     154 * @param[in] fun Device function the action was invoked on.
     155 * @param[in] target Target pipe (address and endpoint number) specification.
     156 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
     157 *      by the caller).
     158 * @param[in] size Size of the @p data buffer in bytes.
     159 * @param[in] callback Callback to be issued once the transfer is complete.
     160 * @param[in] arg Pass-through argument to the callback.
     161 * @return Error code.
     162 */
     163static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
     164    void *data, size_t size,
     165    usbhc_iface_transfer_out_callback_t callback, void *arg)
     166{
     167        UNSUPPORTED("interrupt_out");
     168
     169        return ENOTSUP;
     170}
     171
     172/** Schedule interrupt in transfer.
     173 *
     174 * The callback is supposed to be called once the transfer (on the wire) is
     175 * complete regardless of the outcome.
     176 * However, the callback could be called only when this function returns
     177 * with success status (i.e. returns EOK).
     178 *
     179 * @param[in] fun Device function the action was invoked on.
     180 * @param[in] target Target pipe (address and endpoint number) specification.
     181 * @param[in] data Buffer where to store the data (in USB endianess,
     182 *      allocated and deallocated by the caller).
     183 * @param[in] size Size of the @p data buffer in bytes.
     184 * @param[in] callback Callback to be issued once the transfer is complete.
     185 * @param[in] arg Pass-through argument to the callback.
     186 * @return Error code.
     187 */
     188static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
     189    void *data, size_t size,
     190    usbhc_iface_transfer_in_callback_t callback, void *arg)
     191{
     192        UNSUPPORTED("interrupt_in");
     193
     194        return ENOTSUP;
     195}
     196
     197/** Schedule bulk out transfer.
     198 *
     199 * The callback is supposed to be called once the transfer (on the wire) is
     200 * complete regardless of the outcome.
     201 * However, the callback could be called only when this function returns
     202 * with success status (i.e. returns EOK).
     203 *
     204 * @param[in] fun Device function the action was invoked on.
     205 * @param[in] target Target pipe (address and endpoint number) specification.
     206 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
     207 *      by the caller).
     208 * @param[in] size Size of the @p data buffer in bytes.
     209 * @param[in] callback Callback to be issued once the transfer is complete.
     210 * @param[in] arg Pass-through argument to the callback.
     211 * @return Error code.
     212 */
     213static int bulk_out(ddf_fun_t *fun, usb_target_t target,
     214    void *data, size_t size,
     215    usbhc_iface_transfer_out_callback_t callback, void *arg)
     216{
     217        UNSUPPORTED("bulk_out");
     218
     219        return ENOTSUP;
     220}
     221
     222/** Schedule bulk in transfer.
     223 *
     224 * The callback is supposed to be called once the transfer (on the wire) is
     225 * complete regardless of the outcome.
     226 * However, the callback could be called only when this function returns
     227 * with success status (i.e. returns EOK).
     228 *
     229 * @param[in] fun Device function the action was invoked on.
     230 * @param[in] target Target pipe (address and endpoint number) specification.
     231 * @param[in] data Buffer where to store the data (in USB endianess,
     232 *      allocated and deallocated by the caller).
     233 * @param[in] size Size of the @p data buffer in bytes.
     234 * @param[in] callback Callback to be issued once the transfer is complete.
     235 * @param[in] arg Pass-through argument to the callback.
     236 * @return Error code.
     237 */
     238static int bulk_in(ddf_fun_t *fun, usb_target_t target,
     239    void *data, size_t size,
     240    usbhc_iface_transfer_in_callback_t callback, void *arg)
     241{
     242        UNSUPPORTED("bulk_in");
     243
     244        return ENOTSUP;
     245}
     246
     247/** Schedule control write transfer.
     248 *
     249 * The callback is supposed to be called once the transfer (on the wire) is
     250 * complete regardless of the outcome.
     251 * However, the callback could be called only when this function returns
     252 * with success status (i.e. returns EOK).
     253 *
     254 * @param[in] fun Device function the action was invoked on.
     255 * @param[in] target Target pipe (address and endpoint number) specification.
     256 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
     257 *      and deallocated by the caller).
     258 * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
     259 * @param[in] data_buffer Data buffer (in USB endianess, allocated and
     260 *      deallocated by the caller).
     261 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
     262 * @param[in] callback Callback to be issued once the transfer is complete.
     263 * @param[in] arg Pass-through argument to the callback.
     264 * @return Error code.
     265 */
     266static int control_write(ddf_fun_t *fun, usb_target_t target,
     267    void *setup_packet, size_t setup_packet_size,
     268    void *data_buffer, size_t data_buffer_size,
     269    usbhc_iface_transfer_out_callback_t callback, void *arg)
     270{
     271        UNSUPPORTED("control_write");
     272
     273        return ENOTSUP;
     274}
     275
     276/** Schedule control read transfer.
     277 *
     278 * The callback is supposed to be called once the transfer (on the wire) is
     279 * complete regardless of the outcome.
     280 * However, the callback could be called only when this function returns
     281 * with success status (i.e. returns EOK).
     282 *
     283 * @param[in] fun Device function the action was invoked on.
     284 * @param[in] target Target pipe (address and endpoint number) specification.
     285 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
     286 *      and deallocated by the caller).
     287 * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
     288 * @param[in] data_buffer Buffer where to store the data (in USB endianess,
     289 *      allocated and deallocated by the caller).
     290 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
     291 * @param[in] callback Callback to be issued once the transfer is complete.
     292 * @param[in] arg Pass-through argument to the callback.
     293 * @return Error code.
     294 */
     295static int control_read(ddf_fun_t *fun, usb_target_t target,
     296    void *setup_packet, size_t setup_packet_size,
     297    void *data_buffer, size_t data_buffer_size,
     298    usbhc_iface_transfer_in_callback_t callback, void *arg)
     299{
     300        UNSUPPORTED("control_read");
     301
     302        return ENOTSUP;
     303}
     304
    147305/** Host controller interface implementation for EHCI. */
    148306usbhc_iface_t ehci_hc_iface = {
     
    154312        .register_endpoint = register_endpoint,
    155313        .unregister_endpoint = unregister_endpoint,
     314
     315        .interrupt_out = interrupt_out,
     316        .interrupt_in = interrupt_in,
     317
     318        .bulk_out = bulk_out,
     319        .bulk_in = bulk_in,
     320
     321        .control_write = control_write,
     322        .control_read = control_read
    156323};
    157324
  • uspace/drv/bus/usb/ohci/Makefile

    rf1d6866 r85ff862  
    4444
    4545SOURCES = \
     46        batch.c \
    4647        endpoint_list.c \
    4748        hc.c \
     49        hcd_endpoint.c \
     50        iface.c \
    4851        main.c \
    4952        ohci.c \
    50         ohci_batch.c \
    51         ohci_endpoint.c \
    5253        pci.c \
    5354        root_hub.c \
  • uspace/drv/bus/usb/ohci/endpoint_list.c

    rf1d6866 r85ff862  
    8787 * The endpoint is added to the end of the list and queue.
    8888 */
    89 void endpoint_list_add_ep(endpoint_list_t *instance, ohci_endpoint_t *ep)
     89void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
    9090{
    9191        assert(instance);
    92         assert(ep);
    93         usb_log_debug2("Queue %s: Adding endpoint(%p).\n", instance->name, ep);
     92        assert(hcd_ep);
     93        usb_log_debug2("Queue %s: Adding endpoint(%p).\n",
     94            instance->name, hcd_ep);
    9495
    9596        fibril_mutex_lock(&instance->guard);
     
    102103        } else {
    103104                /* There are active EDs, get the last one */
    104                 ohci_endpoint_t *last = list_get_instance(
    105                     list_last(&instance->endpoint_list), ohci_endpoint_t, link);
     105                hcd_endpoint_t *last = list_get_instance(
     106                    list_last(&instance->endpoint_list), hcd_endpoint_t, link);
    106107                last_ed = last->ed;
    107108        }
    108109        /* Keep link */
    109         ep->ed->next = last_ed->next;
     110        hcd_ep->ed->next = last_ed->next;
    110111        /* Make sure ED is written to the memory */
    111112        write_barrier();
    112113
    113114        /* Add ed to the hw queue */
    114         ed_append_ed(last_ed, ep->ed);
     115        ed_append_ed(last_ed, hcd_ep->ed);
    115116        /* Make sure ED is updated */
    116117        write_barrier();
    117118
    118119        /* Add to the sw list */
    119         list_append(&ep->link, &instance->endpoint_list);
     120        list_append(&hcd_ep->link, &instance->endpoint_list);
    120121
    121         ohci_endpoint_t *first = list_get_instance(
    122             list_first(&instance->endpoint_list), ohci_endpoint_t, link);
     122        hcd_endpoint_t *first = list_get_instance(
     123            list_first(&instance->endpoint_list), hcd_endpoint_t, link);
    123124        usb_log_debug("HCD EP(%p) added to list %s, first is %p(%p).\n",
    124                 ep, instance->name, first, first->ed);
     125                hcd_ep, instance->name, first, first->ed);
    125126        if (last_ed == instance->list_head) {
    126127                usb_log_debug2("%s head ED(%p-0x%0" PRIx32 "): %x:%x:%x:%x.\n",
     
    137138 * @param[in] endpoint Endpoint to remove.
    138139 */
    139 void endpoint_list_remove_ep(endpoint_list_t *instance, ohci_endpoint_t *ep)
     140void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
    140141{
    141142        assert(instance);
    142143        assert(instance->list_head);
    143         assert(ep);
    144         assert(ep->ed);
     144        assert(hcd_ep);
     145        assert(hcd_ep->ed);
    145146
    146147        fibril_mutex_lock(&instance->guard);
    147148
    148         usb_log_debug2("Queue %s: removing endpoint(%p).\n", instance->name, ep);
     149        usb_log_debug2(
     150            "Queue %s: removing endpoint(%p).\n", instance->name, hcd_ep);
    149151
    150152        const char *qpos = NULL;
    151153        ed_t *prev_ed;
    152154        /* Remove from the hardware queue */
    153         if (list_first(&instance->endpoint_list) == &ep->link) {
     155        if (list_first(&instance->endpoint_list) == &hcd_ep->link) {
    154156                /* I'm the first one here */
    155157                prev_ed = instance->list_head;
    156158                qpos = "FIRST";
    157159        } else {
    158                 ohci_endpoint_t *prev =
    159                     list_get_instance(ep->link.prev, ohci_endpoint_t, link);
     160                hcd_endpoint_t *prev =
     161                    list_get_instance(hcd_ep->link.prev, hcd_endpoint_t, link);
    160162                prev_ed = prev->ed;
    161163                qpos = "NOT FIRST";
    162164        }
    163         assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(ep->ed));
    164         prev_ed->next = ep->ed->next;
     165        assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed));
     166        prev_ed->next = hcd_ep->ed->next;
    165167        /* Make sure ED is updated */
    166168        write_barrier();
    167169
    168170        usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n",
    169             ep, qpos, instance->name, ep->ed->next);
     171            hcd_ep, qpos, instance->name, hcd_ep->ed->next);
    170172
    171173        /* Remove from the endpoint list */
    172         list_remove(&ep->link);
     174        list_remove(&hcd_ep->link);
    173175        fibril_mutex_unlock(&instance->guard);
    174176}
  • uspace/drv/bus/usb/ohci/endpoint_list.h

    rf1d6866 r85ff862  
    3737#include <fibril_synch.h>
    3838
    39 #include "ohci_endpoint.h"
     39#include "hcd_endpoint.h"
    4040#include "hw_struct/endpoint_descriptor.h"
    4141#include "utils/malloc32.h"
     
    6969int endpoint_list_init(endpoint_list_t *instance, const char *name);
    7070void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next);
    71 void endpoint_list_add_ep(endpoint_list_t *instance, ohci_endpoint_t *ep);
    72 void endpoint_list_remove_ep(endpoint_list_t *instance, ohci_endpoint_t *ep);
     71void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
     72void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
    7373#endif
    7474/**
  • uspace/drv/bus/usb/ohci/hc.c

    rf1d6866 r85ff862  
    4242
    4343#include "hc.h"
    44 #include "ohci_endpoint.h"
     44#include "hcd_endpoint.h"
    4545
    4646#define OHCI_USED_INTERRUPTS \
     
    6161static int hc_init_memory(hc_t *instance);
    6262static int interrupt_emulator(hc_t *instance);
    63 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
     63
    6464/*----------------------------------------------------------------------------*/
    6565/** Get number of commands used in IRQ code.
     
    128128
    129129        const usb_address_t hub_address =
    130             usb_device_manager_get_free_address(
    131                 &instance->generic.dev_manager, USB_SPEED_FULL);
     130            device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL);
    132131        if (hub_address <= 0) {
    133132                usb_log_error("Failed to get OHCI root hub address: %s\n",
     
    136135        }
    137136        instance->rh.address = hub_address;
    138         usb_device_manager_bind(
    139             &instance->generic.dev_manager, hub_address, hub_fun->handle);
    140 
    141 #define CHECK_RET_UNREG_RETURN(ret, message...) \
     137        usb_device_keeper_bind(
     138            &instance->manager, hub_address, hub_fun->handle);
     139
     140#define CHECK_RET_RELEASE(ret, message...) \
    142141if (ret != EOK) { \
    143142        usb_log_error(message); \
    144         usb_endpoint_manager_unregister_ep( \
    145             &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH);\
    146         usb_device_manager_release( \
    147             &instance->generic.dev_manager, hub_address); \
     143        hc_remove_endpoint(instance, hub_address, 0, USB_DIRECTION_BOTH); \
     144        usb_device_keeper_release(&instance->manager, hub_address); \
    148145        return ret; \
    149146} else (void)0
    150         int ret = usb_endpoint_manager_add_ep(
    151             &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH,
    152             USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0);
    153         CHECK_RET_UNREG_RETURN(ret,
    154             "Failed to register root hub control endpoint: %s.\n",
    155             str_error(ret));
     147
     148        int ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
     149            USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
     150        CHECK_RET_RELEASE(ret,
     151            "Failed to add OHCI root hub endpoint 0: %s.\n", str_error(ret));
    156152
    157153        ret = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100);
    158         CHECK_RET_UNREG_RETURN(ret,
     154        CHECK_RET_RELEASE(ret,
    159155            "Failed to add root hub match-id: %s.\n", str_error(ret));
    160156
    161157        ret = ddf_fun_bind(hub_fun);
    162         CHECK_RET_UNREG_RETURN(ret,
     158        CHECK_RET_RELEASE(ret,
    163159            "Failed to bind root hub function: %s.\n", str_error(ret));
    164160
     
    191187
    192188        list_initialize(&instance->pending_batches);
    193 
    194         ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
    195             bandwidth_count_usb11);
    196         CHECK_RET_RETURN(ret, "Failed to initialize generic driver: %s.\n",
     189        usb_device_keeper_init(&instance->manager);
     190
     191        ret = usb_endpoint_manager_init(&instance->ep_manager,
     192            BANDWIDTH_AVAILABLE_USB11);
     193        CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
    197194            str_error(ret));
    198         instance->generic.private_data = instance;
    199         instance->generic.schedule = hc_schedule;
    200         instance->generic.ep_add_hook = ohci_endpoint_init;
    201195
    202196        ret = hc_init_memory(instance);
     
    221215}
    222216/*----------------------------------------------------------------------------*/
    223 void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep)
    224 {
    225         endpoint_list_t *list = &instance->lists[ep->transfer_type];
    226         ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep);
    227         /* Enqueue ep */
     217/** Create and register endpoint structures.
     218 *
     219 * @param[in] instance OHCI driver structure.
     220 * @param[in] address USB address of the device.
     221 * @param[in] endpoint USB endpoint number.
     222 * @param[in] speed Communication speeed of the device.
     223 * @param[in] type Endpoint's transfer type.
     224 * @param[in] direction Endpoint's direction.
     225 * @param[in] mps Maximum packet size the endpoint accepts.
     226 * @param[in] size Maximum allowed buffer size.
     227 * @param[in] interval Time between transfers(interrupt transfers only).
     228 * @return Error code
     229 */
     230int hc_add_endpoint(
     231    hc_t *instance, usb_address_t address, usb_endpoint_t endpoint,
     232    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
     233    size_t mps, size_t size, unsigned interval)
     234{
     235        endpoint_t *ep =
     236            endpoint_get(address, endpoint, direction, type, speed, mps);
     237        if (ep == NULL)
     238                return ENOMEM;
     239
     240        hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep);
     241        if (hcd_ep == NULL) {
     242                endpoint_destroy(ep);
     243                return ENOMEM;
     244        }
     245
     246        int ret =
     247            usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
     248        if (ret != EOK) {
     249                hcd_endpoint_clear(ep);
     250                endpoint_destroy(ep);
     251                return ret;
     252        }
     253
     254        /* Enqueue hcd_ep */
    228255        switch (ep->transfer_type) {
    229256        case USB_TRANSFER_CONTROL:
    230257                instance->registers->control &= ~C_CLE;
    231                 endpoint_list_add_ep(list, ohci_ep);
     258                endpoint_list_add_ep(
     259                    &instance->lists[ep->transfer_type], hcd_ep);
    232260                instance->registers->control_current = 0;
    233261                instance->registers->control |= C_CLE;
     
    235263        case USB_TRANSFER_BULK:
    236264                instance->registers->control &= ~C_BLE;
    237                 endpoint_list_add_ep(list, ohci_ep);
     265                endpoint_list_add_ep(
     266                    &instance->lists[ep->transfer_type], hcd_ep);
    238267                instance->registers->control |= C_BLE;
    239268                break;
     
    241270        case USB_TRANSFER_INTERRUPT:
    242271                instance->registers->control &= (~C_PLE & ~C_IE);
    243                 endpoint_list_add_ep(list, ohci_ep);
     272                endpoint_list_add_ep(
     273                    &instance->lists[ep->transfer_type], hcd_ep);
    244274                instance->registers->control |= C_PLE | C_IE;
    245275                break;
    246276        }
    247 }
    248 /*----------------------------------------------------------------------------*/
    249 void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep)
    250 {
    251         /* Dequeue ep */
    252         endpoint_list_t *list = &instance->lists[ep->transfer_type];
    253         ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep);
    254         switch (ep->transfer_type) {
    255         case USB_TRANSFER_CONTROL:
    256                 instance->registers->control &= ~C_CLE;
    257                 endpoint_list_remove_ep(list, ohci_ep);
    258                 instance->registers->control_current = 0;
    259                 instance->registers->control |= C_CLE;
    260                 break;
    261         case USB_TRANSFER_BULK:
    262                 instance->registers->control &= ~C_BLE;
    263                 endpoint_list_remove_ep(list, ohci_ep);
    264                 instance->registers->control |= C_BLE;
    265                 break;
    266         case USB_TRANSFER_ISOCHRONOUS:
    267         case USB_TRANSFER_INTERRUPT:
    268                 instance->registers->control &= (~C_PLE & ~C_IE);
    269                 endpoint_list_remove_ep(list, ohci_ep);
    270                 instance->registers->control |= C_PLE | C_IE;
    271                 break;
    272         default:
    273                 break;
    274         }
     277
     278        return EOK;
     279}
     280/*----------------------------------------------------------------------------*/
     281/** Dequeue and delete endpoint structures
     282 *
     283 * @param[in] instance OHCI hc driver structure.
     284 * @param[in] address USB address of the device.
     285 * @param[in] endpoint USB endpoint number.
     286 * @param[in] direction Direction of the endpoint.
     287 * @return Error code
     288 */
     289int hc_remove_endpoint(hc_t *instance, usb_address_t address,
     290    usb_endpoint_t endpoint, usb_direction_t direction)
     291{
     292        assert(instance);
     293        fibril_mutex_lock(&instance->guard);
     294        endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
     295            address, endpoint, direction, NULL);
     296        if (ep == NULL) {
     297                usb_log_error("Endpoint unregister failed: No such EP.\n");
     298                fibril_mutex_unlock(&instance->guard);
     299                return ENOENT;
     300        }
     301
     302        hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
     303        if (hcd_ep) {
     304                /* Dequeue hcd_ep */
     305                switch (ep->transfer_type) {
     306                case USB_TRANSFER_CONTROL:
     307                        instance->registers->control &= ~C_CLE;
     308                        endpoint_list_remove_ep(
     309                            &instance->lists[ep->transfer_type], hcd_ep);
     310                        instance->registers->control_current = 0;
     311                        instance->registers->control |= C_CLE;
     312                        break;
     313                case USB_TRANSFER_BULK:
     314                        instance->registers->control &= ~C_BLE;
     315                        endpoint_list_remove_ep(
     316                            &instance->lists[ep->transfer_type], hcd_ep);
     317                        instance->registers->control |= C_BLE;
     318                        break;
     319                case USB_TRANSFER_ISOCHRONOUS:
     320                case USB_TRANSFER_INTERRUPT:
     321                        instance->registers->control &= (~C_PLE & ~C_IE);
     322                        endpoint_list_remove_ep(
     323                            &instance->lists[ep->transfer_type], hcd_ep);
     324                        instance->registers->control |= C_PLE | C_IE;
     325                        break;
     326                default:
     327                        break;
     328                }
     329                hcd_endpoint_clear(ep);
     330        } else {
     331                usb_log_warning("Endpoint without hcd equivalent structure.\n");
     332        }
     333        int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager,
     334            address, endpoint, direction);
     335        fibril_mutex_unlock(&instance->guard);
     336        return ret;
     337}
     338/*----------------------------------------------------------------------------*/
     339/** Get access to endpoint structures
     340 *
     341 * @param[in] instance OHCI hc driver structure.
     342 * @param[in] address USB address of the device.
     343 * @param[in] endpoint USB endpoint number.
     344 * @param[in] direction Direction of the endpoint.
     345 * @param[out] bw Reserved bandwidth.
     346 * @return Error code
     347 */
     348endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
     349    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw)
     350{
     351        assert(instance);
     352        fibril_mutex_lock(&instance->guard);
     353        endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
     354            address, endpoint, direction, bw);
     355        fibril_mutex_unlock(&instance->guard);
     356        return ep;
    275357}
    276358/*----------------------------------------------------------------------------*/
     
    281363 * @return Error code.
    282364 */
    283 int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
    284 {
    285         assert(hcd);
    286         hc_t *instance = hcd->private_data;
    287         assert(instance);
     365int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
     366{
     367        assert(instance);
     368        assert(batch);
     369        assert(batch->ep);
    288370
    289371        /* Check for root hub communication */
     
    292374                return EOK;
    293375        }
    294         ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch);
    295         if (!ohci_batch)
    296                 return ENOMEM;
    297376
    298377        fibril_mutex_lock(&instance->guard);
    299         list_append(&ohci_batch->link, &instance->pending_batches);
    300         ohci_transfer_batch_commit(ohci_batch);
     378        list_append(&batch->link, &instance->pending_batches);
     379        batch_commit(batch);
    301380
    302381        /* Control and bulk schedules need a kick to start working */
     
    338417                    instance->registers->periodic_current);
    339418
    340                 link_t *current = list_first(&instance->pending_batches);
    341                 while (current && current != &instance->pending_batches.head) {
     419                link_t *current = instance->pending_batches.head.next;
     420                while (current != &instance->pending_batches.head) {
    342421                        link_t *next = current->next;
    343                         ohci_transfer_batch_t *batch =
    344                             ohci_transfer_batch_from_link(current);
    345 
    346                         if (ohci_transfer_batch_is_complete(batch)) {
     422                        usb_transfer_batch_t *batch =
     423                            usb_transfer_batch_from_link(current);
     424
     425                        if (batch_is_complete(batch)) {
    347426                                list_remove(current);
    348                                 ohci_transfer_batch_finish_dispose(batch);
     427                                usb_transfer_batch_finish(batch);
    349428                        }
    350429
     
    355434
    356435        if (status & I_UE) {
    357                 usb_log_fatal("Error like no other!\n");
    358436                hc_start(instance);
    359437        }
  • uspace/drv/bus/usb/ohci/hc.h

    rf1d6866 r85ff862  
    4141
    4242#include <usb/usb.h>
    43 #include <usb/host/hcd.h>
     43#include <usb/host/device_keeper.h>
     44#include <usb/host/usb_endpoint_manager.h>
     45#include <usbhc_iface.h>
    4446
    45 #include "ohci_batch.h"
     47#include "batch.h"
    4648#include "ohci_regs.h"
    4749#include "root_hub.h"
     
    5153/** Main OHCI driver structure */
    5254typedef struct hc {
    53         /** Generic USB hc driver */
    54         hcd_t generic;
     55        /** USB bus driver, devices and addresses */
     56        usb_device_keeper_t manager;
     57        /** USB bus driver, endpoints */
     58        usb_endpoint_manager_t ep_manager;
    5559
    5660        /** Memory mapped I/O registers area */
     
    7781int hc_get_irq_commands(
    7882    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
     83int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
    7984int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
    80 int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
    8185
    8286/** Safely dispose host controller internal structures
     
    8488 * @param[in] instance Host controller structure to use.
    8589 */
    86 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
     90static inline void hc_fini(hc_t *instance)
     91        { /* TODO: implement*/ };
    8792
    88 void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep);
    89 void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep);
     93int hc_add_endpoint(hc_t *instance, usb_address_t address, usb_endpoint_t ep,
     94    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
     95    size_t max_packet_size, size_t size, unsigned interval);
     96int hc_remove_endpoint(hc_t *instance, usb_address_t address,
     97    usb_endpoint_t endpoint, usb_direction_t direction);
     98endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
     99    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw);
    90100
     101int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
    91102void hc_interrupt(hc_t *instance, uint32_t status);
     103
     104/** Get and cast pointer to the driver data
     105 *
     106 * @param[in] fun DDF function pointer
     107 * @return cast pointer to driver_data
     108 */
     109static inline hc_t * fun_to_hc(ddf_fun_t *fun)
     110        { return fun->driver_data; }
    92111#endif
    93112/**
  • uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c

    rf1d6866 r85ff862  
    3939static unsigned togg[2] = { TD_STATUS_T_0, TD_STATUS_T_1 };
    4040
    41 void td_init(td_t *instance,
    42     usb_direction_t dir, const void *buffer, size_t size, int toggle)
     41void td_init(
     42    td_t *instance, usb_direction_t dir, void *buffer, size_t size, int toggle)
    4343{
    4444        assert(instance);
  • uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h

    rf1d6866 r85ff862  
    7575} __attribute__((packed)) td_t;
    7676
    77 void td_init(td_t *instance,
    78     usb_direction_t dir, const void *buffer, size_t size, int toggle);
     77void td_init(
     78    td_t *instance, usb_direction_t dir, void *buffer, size_t size, int toggle);
    7979
    8080inline static void td_set_next(td_t *instance, td_t *next)
  • uspace/drv/bus/usb/ohci/ohci.c

    rf1d6866 r85ff862  
    4242
    4343#include "ohci.h"
     44#include "iface.h"
    4445#include "pci.h"
    4546#include "hc.h"
     47#include "root_hub.h"
    4648
    4749typedef struct ohci {
     
    5052
    5153        hc_t hc;
     54        rh_t rh;
    5255} ohci_t;
    5356
     
    8689{
    8790        assert(fun);
    88         usb_device_manager_t *manager =
    89             &dev_to_ohci(fun->dev)->hc.generic.dev_manager;
    90 
    91         const usb_address_t addr = usb_device_manager_find(manager, handle);
     91        usb_device_keeper_t *manager = &dev_to_ohci(fun->dev)->hc.manager;
     92
     93        usb_address_t addr = usb_device_keeper_find(manager, handle);
    9294        if (addr < 0) {
    9395                return addr;
     
    127129/** Standard USB HC options (HC interface) */
    128130static ddf_dev_ops_t hc_ops = {
    129         .interfaces[USBHC_DEV_IFACE] = &hcd_iface,
     131        .interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
    130132};
    131133/*----------------------------------------------------------------------------*/
     
    148150int device_setup_ohci(ddf_dev_t *device)
    149151{
    150         assert(device);
    151 
    152152        ohci_t *instance = malloc(sizeof(ohci_t));
    153153        if (instance == NULL) {
     
    155155                return ENOMEM;
    156156        }
    157         instance->rh_fun = NULL;
    158         instance->hc_fun = NULL;
    159157
    160158#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
    161159if (ret != EOK) { \
    162160        if (instance->hc_fun) { \
     161                instance->hc_fun->ops = NULL; \
     162                instance->hc_fun->driver_data = NULL; \
    163163                ddf_fun_destroy(instance->hc_fun); \
    164164        } \
    165165        if (instance->rh_fun) { \
     166                instance->rh_fun->ops = NULL; \
     167                instance->rh_fun->driver_data = NULL; \
    166168                ddf_fun_destroy(instance->rh_fun); \
    167169        } \
    168170        free(instance); \
     171        device->driver_data = NULL; \
    169172        usb_log_error(message); \
    170173        return ret; \
    171174} else (void)0
    172175
     176        instance->rh_fun = NULL;
    173177        instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc");
    174178        int ret = instance->hc_fun ? EOK : ENOMEM;
     
    190194        ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
    191195        CHECK_RET_DEST_FREE_RETURN(ret,
    192             "Failed to get register memory addresses for %" PRIun ": %s.\n",
     196            "Failed to get memory addresses for %" PRIun ": %s.\n",
    193197            device->handle, str_error(ret));
    194198        usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
     
    197201        const size_t cmd_count = hc_irq_cmd_count();
    198202        irq_cmd_t irq_cmds[cmd_count];
    199         irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
    200 
    201203        ret =
    202204            hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
     
    204206            "Failed to generate IRQ commands: %s.\n", str_error(ret));
    205207
     208        irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
    206209
    207210        /* Register handler to avoid interrupt lockup */
     
    231234#define CHECK_RET_FINI_RETURN(ret, message...) \
    232235if (ret != EOK) { \
     236        unregister_interrupt_handler(device, irq); \
    233237        hc_fini(&instance->hc); \
    234         unregister_interrupt_handler(device, irq); \
    235238        CHECK_RET_DEST_FREE_RETURN(ret, message); \
    236239} else (void)0
     
    245248            "Failed to add OHCI to HC class: %s.\n", str_error(ret));
    246249
    247         ret = hc_register_hub(&instance->hc, instance->rh_fun);
    248         CHECK_RET_FINI_RETURN(ret,
    249             "Failed to register OHCI root hub: %s.\n", str_error(ret));
    250         return ret;
    251 
     250        hc_register_hub(&instance->hc, instance->rh_fun);
     251        return EOK;
     252
     253#undef CHECK_RET_DEST_FUN_RETURN
    252254#undef CHECK_RET_FINI_RETURN
    253255}
  • uspace/drv/bus/usb/ohci/pci.c

    rf1d6866 r85ff862  
    7070        if (!parent_sess)
    7171                return ENOMEM;
    72 
     72       
    7373        hw_resource_list_t hw_resources;
    7474        int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
    75         async_hangup(parent_sess);
    7675        if (rc != EOK) {
     76                async_hangup(parent_sess);
    7777                return rc;
    7878        }
    79 
     79       
    8080        uintptr_t mem_address = 0;
    8181        size_t mem_size = 0;
    8282        bool mem_found = false;
    83 
     83       
    8484        int irq = 0;
    8585        bool irq_found = false;
    86 
     86       
    8787        size_t i;
    8888        for (i = 0; i < hw_resources.count; i++) {
     
    107107                }
    108108        }
    109         free(hw_resources.resources);
    110 
     109       
    111110        if (mem_found && irq_found) {
    112111                *mem_reg_address = mem_address;
    113112                *mem_reg_size = mem_size;
    114113                *irq_no = irq;
    115                 return EOK;
    116         }
    117         return ENOENT;
     114                rc = EOK;
     115        } else
     116                rc = ENOENT;
     117       
     118        async_hangup(parent_sess);
     119        return rc;
    118120}
    119121
  • uspace/drv/bus/usb/ohci/root_hub.c

    rf1d6866 r85ff862  
    121121        assert(request);
    122122
     123        memcpy(request->data_buffer, &mask, size);
    123124        request->transfered_size = size;
    124         usb_transfer_batch_finish_error(request, &mask, size, EOK);
     125        usb_transfer_batch_finish_error(request, EOK);
    125126}
    126127
     
    205206                usb_log_debug("Root hub got CONTROL packet\n");
    206207                const int ret = control_request(instance, request);
    207                 usb_transfer_batch_finish_error(request, NULL, 0, ret);
     208                usb_transfer_batch_finish_error(request, ret);
    208209                break;
    209210        case USB_TRANSFER_INTERRUPT:
     
    214215                        assert(instance->unfinished_interrupt_transfer == NULL);
    215216                        instance->unfinished_interrupt_transfer = request;
    216                         return;
     217                        break;
    217218                }
    218219                usb_log_debug("Processing changes...\n");
     
    222223        default:
    223224                usb_log_error("Root hub got unsupported request.\n");
    224                 usb_transfer_batch_finish_error(request, NULL, 0, EINVAL);
    225         }
    226         usb_transfer_batch_dispose(request);
     225                usb_transfer_batch_finish_error(request, EINVAL);
     226        }
    227227}
    228228/*----------------------------------------------------------------------------*/
     
    244244        interrupt_request(instance->unfinished_interrupt_transfer,
    245245            mask, instance->interrupt_mask_size);
    246         usb_transfer_batch_dispose(instance->unfinished_interrupt_transfer);
    247246
    248247        instance->unfinished_interrupt_transfer = NULL;
     
    390389                const uint32_t data = instance->registers->rh_status &
    391390                    (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG);
    392                 memcpy(request->buffer, &data, sizeof(data));
    393                 TRANSFER_OK(sizeof(data));
     391                memcpy(request->data_buffer, &data, 4);
     392                TRANSFER_OK(4);
    394393        }
    395394
     
    403402                const uint32_t data =
    404403                    instance->registers->rh_port_status[port - 1];
    405                 memcpy(request->buffer, &data, sizeof(data));
    406                 TRANSFER_OK(sizeof(data));
     404                memcpy(request->data_buffer, &data, 4);
     405                TRANSFER_OK(4);
    407406        }
    408407
     
    484483        }
    485484
    486         memcpy(request->buffer, descriptor, size);
     485        memcpy(request->data_buffer, descriptor, size);
    487486        TRANSFER_OK(size);
    488487}
     
    714713                if (request->buffer_size != 1)
    715714                        return EINVAL;
    716                 request->buffer[0] = 1;
     715                request->data_buffer[0] = 1;
    717716                TRANSFER_OK(1);
    718717
  • uspace/drv/bus/usb/ohci/root_hub.h

    rf1d6866 r85ff862  
    3737#include <usb/usb.h>
    3838#include <usb/dev/driver.h>
    39 #include <usb/host/usb_transfer_batch.h>
    4039
    4140#include "ohci_regs.h"
     41#include "batch.h"
    4242
    4343#define HUB_DESCRIPTOR_MAX_SIZE (7 + 2 + 2)
     
    6666        /** size of hub descriptor */
    6767        size_t hub_descriptor_size;
     68
    6869} rh_t;
    6970
  • uspace/drv/bus/usb/ohci/utils/malloc32.h

    rf1d6866 r85ff862  
    4646 * @return Physical address if exists, NULL otherwise.
    4747 */
    48 static inline uintptr_t addr_to_phys(const void *addr)
     48static inline uintptr_t addr_to_phys(void *addr)
    4949{
    5050        uintptr_t result;
  • uspace/drv/bus/usb/uhci/Makefile

    rf1d6866 r85ff862  
    4242
    4343SOURCES = \
    44         hc.c \
     44        iface.c \
    4545        main.c \
    46         pci.c \
    47         root_hub.c \
    4846        transfer_list.c \
    4947        uhci.c \
    50         uhci_batch.c \
    51         hw_struct/transfer_descriptor.c
     48        hc.c \
     49        root_hub.c \
     50        hw_struct/transfer_descriptor.c \
     51        pci.c \
     52        batch.c
    5253
    5354include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/bus/usb/uhci/hc.c

    rf1d6866 r85ff862  
    4141
    4242#include "hc.h"
    43 #include "uhci_batch.h"
    4443
    4544#define UHCI_INTR_ALLOW_INTERRUPTS \
     
    4746#define UHCI_STATUS_USED_INTERRUPTS \
    4847    (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
    49 
    5048
    5149static const irq_cmd_t uhci_irq_commands[] =
     
    5957};
    6058
    61 static void hc_init_hw(const hc_t *instance);
     59static int hc_init_transfer_lists(hc_t *instance);
    6260static int hc_init_mem_structures(hc_t *instance);
    63 static int hc_init_transfer_lists(hc_t *instance);
    64 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
     61static void hc_init_hw(hc_t *instance);
    6562
    6663static int hc_interrupt_emulator(void *arg);
     
    9895        cmds[3].addr = (void*)&registers->usbsts;
    9996        return EOK;
    100 }
    101 /*----------------------------------------------------------------------------*/
    102 /** Take action based on the interrupt cause.
    103  *
    104  * @param[in] instance UHCI structure to use.
    105  * @param[in] status Value of the status register at the time of interrupt.
    106  *
    107  * Interrupt might indicate:
    108  * - transaction completed, either by triggering IOC, SPD, or an error
    109  * - some kind of device error
    110  * - resume from suspend state (not implemented)
    111  */
    112 void hc_interrupt(hc_t *instance, uint16_t status)
    113 {
    114         assert(instance);
    115         /* Lower 2 bits are transaction error and transaction complete */
    116         if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
    117                 LIST_INITIALIZE(done);
    118                 transfer_list_remove_finished(
    119                     &instance->transfers_interrupt, &done);
    120                 transfer_list_remove_finished(
    121                     &instance->transfers_control_slow, &done);
    122                 transfer_list_remove_finished(
    123                     &instance->transfers_control_full, &done);
    124                 transfer_list_remove_finished(
    125                     &instance->transfers_bulk_full, &done);
    126 
    127                 while (!list_empty(&done)) {
    128                         link_t *item = list_first(&done);
    129                         list_remove(item);
    130                         uhci_transfer_batch_t *batch =
    131                             uhci_transfer_batch_from_link(item);
    132                         uhci_transfer_batch_call_dispose(batch);
    133                 }
    134         }
    135         /* Resume interrupts are not supported */
    136         if (status & UHCI_STATUS_RESUME) {
    137                 usb_log_error("Resume interrupt!\n");
    138         }
    139 
    140         /* Bits 4 and 5 indicate hc error */
    141         if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
    142                 usb_log_error("UHCI hardware failure!.\n");
    143                 ++instance->hw_failures;
    144                 transfer_list_abort_all(&instance->transfers_interrupt);
    145                 transfer_list_abort_all(&instance->transfers_control_slow);
    146                 transfer_list_abort_all(&instance->transfers_control_full);
    147                 transfer_list_abort_all(&instance->transfers_bulk_full);
    148 
    149                 if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) {
    150                         /* reinitialize hw, this triggers virtual disconnect*/
    151                         hc_init_hw(instance);
    152                 } else {
    153                         usb_log_fatal("Too many UHCI hardware failures!.\n");
    154                         hc_fini(instance);
    155                 }
    156         }
    15797}
    15898/*----------------------------------------------------------------------------*/
     
    192132            "Device registers at %p (%zuB) accessible.\n", io, reg_size);
    193133
    194         ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
    195             bandwidth_count_usb11);
    196         CHECK_RET_RETURN(ret, "Failed to initialize HCD generic driver: %s.\n",
     134        ret = hc_init_mem_structures(instance);
     135        CHECK_RET_RETURN(ret,
     136            "Failed to initialize UHCI memory structures: %s.\n",
    197137            str_error(ret));
    198 
    199         instance->generic.private_data = instance;
    200         instance->generic.schedule = hc_schedule;
    201         instance->generic.ep_add_hook = NULL;
    202 
    203 #undef CHECK_RET_DEST_FUN_RETURN
    204 
    205         ret = hc_init_mem_structures(instance);
    206         if (ret != EOK) {
    207                 usb_log_error(
    208                     "Failed to initialize UHCI memory structures: %s.\n",
    209                     str_error(ret));
    210                 hcd_destroy(&instance->generic);
    211                 return ret;
    212         }
    213138
    214139        hc_init_hw(instance);
     
    221146
    222147        return EOK;
     148#undef CHECK_RET_DEST_FUN_RETURN
    223149}
    224150/*----------------------------------------------------------------------------*/
     
    228154 * For magic values see UHCI Design Guide
    229155 */
    230 void hc_init_hw(const hc_t *instance)
     156void hc_init_hw(hc_t *instance)
    231157{
    232158        assert(instance);
     
    272198 *
    273199 * Structures:
     200 *  - interrupt code (I/O addressses are customized per instance)
    274201 *  - transfer lists (queue heads need to be accessible by the hw)
    275202 *  - frame list page (needs to be one UHCI hw accessible 4K page)
     
    278205{
    279206        assert(instance);
    280 
    281         /* Init USB frame list page */
     207#define CHECK_RET_RETURN(ret, message...) \
     208        if (ret != EOK) { \
     209                usb_log_error(message); \
     210                return ret; \
     211        } else (void) 0
     212
     213        /* Init transfer lists */
     214        int ret = hc_init_transfer_lists(instance);
     215        CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
     216        usb_log_debug("Initialized transfer lists.\n");
     217
     218        /* Init device keeper */
     219        usb_device_keeper_init(&instance->manager);
     220        usb_log_debug("Initialized device keeper.\n");
     221
     222        ret = usb_endpoint_manager_init(&instance->ep_manager,
     223            BANDWIDTH_AVAILABLE_USB11);
     224        CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
     225            str_error(ret));
     226
     227        /* Init USB frame list page*/
    282228        instance->frame_list = get_page();
    283229        if (!instance->frame_list) {
     230                usb_log_error("Failed to get frame list page.\n");
     231                usb_endpoint_manager_destroy(&instance->ep_manager);
    284232                return ENOMEM;
    285233        }
    286234        usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
    287 
    288         /* Init transfer lists */
    289         int ret = hc_init_transfer_lists(instance);
    290         if (ret != EOK) {
    291                 usb_log_error("Failed to initialize transfer lists.\n");
    292                 return_page(instance->frame_list);
    293                 return ENOMEM;
    294         }
    295         usb_log_debug("Initialized transfer lists.\n");
    296 
    297235
    298236        /* Set all frames to point to the first queue head */
     
    305243
    306244        return EOK;
     245#undef CHECK_RET_RETURN
    307246}
    308247/*----------------------------------------------------------------------------*/
     
    377316 * Checks for bandwidth availability and appends the batch to the proper queue.
    378317 */
    379 int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
    380 {
    381         assert(hcd);
    382         hc_t *instance = hcd->private_data;
     318int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
     319{
    383320        assert(instance);
    384321        assert(batch);
    385         uhci_transfer_batch_t *uhci_batch = uhci_transfer_batch_get(batch);
    386         if (!uhci_batch) {
    387                 usb_log_error("Failed to create UHCI transfer structures.\n");
    388                 return ENOMEM;
    389         }
    390322
    391323        transfer_list_t *list =
    392324            instance->transfers[batch->ep->speed][batch->ep->transfer_type];
    393325        assert(list);
    394         transfer_list_add_batch(list, uhci_batch);
    395 
    396         return EOK;
     326        transfer_list_add_batch(list, batch);
     327
     328        return EOK;
     329}
     330/*----------------------------------------------------------------------------*/
     331/** Take action based on the interrupt cause.
     332 *
     333 * @param[in] instance UHCI structure to use.
     334 * @param[in] status Value of the status register at the time of interrupt.
     335 *
     336 * Interrupt might indicate:
     337 * - transaction completed, either by triggering IOC, SPD, or an error
     338 * - some kind of device error
     339 * - resume from suspend state (not implemented)
     340 */
     341void hc_interrupt(hc_t *instance, uint16_t status)
     342{
     343        assert(instance);
     344        /* Lower 2 bits are transaction error and transaction complete */
     345        if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
     346                LIST_INITIALIZE(done);
     347                transfer_list_remove_finished(
     348                    &instance->transfers_interrupt, &done);
     349                transfer_list_remove_finished(
     350                    &instance->transfers_control_slow, &done);
     351                transfer_list_remove_finished(
     352                    &instance->transfers_control_full, &done);
     353                transfer_list_remove_finished(
     354                    &instance->transfers_bulk_full, &done);
     355
     356                while (!list_empty(&done)) {
     357                        link_t *item = list_first(&done);
     358                        list_remove(item);
     359                        usb_transfer_batch_t *batch =
     360                            list_get_instance(item, usb_transfer_batch_t, link);
     361                        usb_transfer_batch_finish(batch);
     362                }
     363        }
     364        /* Resume interrupts are not supported */
     365        if (status & UHCI_STATUS_RESUME) {
     366                usb_log_error("Resume interrupt!\n");
     367        }
     368
     369        /* Bits 4 and 5 indicate hc error */
     370        if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
     371                usb_log_error("UHCI hardware failure!.\n");
     372                ++instance->hw_failures;
     373                transfer_list_abort_all(&instance->transfers_interrupt);
     374                transfer_list_abort_all(&instance->transfers_control_slow);
     375                transfer_list_abort_all(&instance->transfers_control_full);
     376                transfer_list_abort_all(&instance->transfers_bulk_full);
     377
     378                if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) {
     379                        /* reinitialize hw, this triggers virtual disconnect*/
     380                        hc_init_hw(instance);
     381                } else {
     382                        usb_log_fatal("Too many UHCI hardware failures!.\n");
     383                        hc_fini(instance);
     384                }
     385        }
    397386}
    398387/*----------------------------------------------------------------------------*/
     
    414403                if (status != 0)
    415404                        usb_log_debug2("UHCI status: %x.\n", status);
     405// Qemu fails to report stalled communication
     406// see https://bugs.launchpad.net/qemu/+bug/757654
     407// This is a simple workaround to force queue processing every time
     408        //      status |= 1;
    416409                hc_interrupt(instance, status);
    417410                async_usleep(UHCI_INT_EMULATOR_TIMEOUT);
     
    419412        return EOK;
    420413}
    421 /*----------------------------------------------------------------------------*/
     414/*---------------------------------------------------------------------------*/
    422415/** Debug function, checks consistency of memory structures.
    423416 *
  • uspace/drv/bus/usb/uhci/hc.h

    rf1d6866 r85ff862  
    3939#include <ddi.h>
    4040
    41 #include <usb/host/hcd.h>
     41#include <usb/host/device_keeper.h>
     42#include <usb/host/usb_endpoint_manager.h>
     43#include <usb/host/batch.h>
    4244
    4345#include "transfer_list.h"
     
    9294/** Main UHCI driver structure */
    9395typedef struct hc {
    94         /** Generic HCD driver structure */
    95         hcd_t generic;
     96        /** USB bus driver, devices and addresses */
     97        usb_device_keeper_t manager;
     98        /** USB bus driver, endpoints */
     99        usb_endpoint_manager_t ep_manager;
    96100
    97101        /** Addresses of I/O registers */
     
    120124        unsigned hw_failures;
    121125} hc_t;
    122 
    123126size_t hc_irq_cmd_count(void);
    124127int hc_get_irq_commands(
    125128    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
     129int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
     130int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
    126131void hc_interrupt(hc_t *instance, uint16_t status);
    127 int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
    128132
    129133/** Safely dispose host controller internal structures
     
    131135 * @param[in] instance Host controller structure to use.
    132136 */
    133 static inline void hc_fini(hc_t *instance) {} /* TODO: implement*/
     137static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
     138
     139/** Get and cast pointer to the driver data
     140 *
     141 * @param[in] fun DDF function pointer
     142 * @return cast pointer to driver_data
     143 */
     144static inline hc_t * fun_to_hc(ddf_fun_t *fun)
     145{
     146        assert(fun);
     147        return fun->driver_data;
     148}
    134149#endif
    135150/**
  • uspace/drv/bus/usb/uhci/hw_struct/link_pointer.h

    rf1d6866 r85ff862  
    3535#define DRV_UHCI_HW_STRUCT_LINK_POINTER_H
    3636
    37 /** UHCI link pointer, used by many data structures */
     37/* UHCI link pointer, used by many data structures */
    3838typedef uint32_t link_pointer_t;
    3939
  • uspace/drv/bus/usb/uhci/hw_struct/queue_head.h

    rf1d6866 r85ff862  
    5858        assert(instance);
    5959
    60         instance->element = LINK_POINTER_TERM;
    61         instance->next = LINK_POINTER_TERM;
     60        instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
     61        instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
    6262}
    6363/*----------------------------------------------------------------------------*/
     
    7171static inline void qh_set_next_qh(qh_t *instance, qh_t *next)
    7272{
    73         /* Physical address has to be below 4GB,
    74          * it is an UHCI limitation and malloc32
    75          * should guarantee this */
    76         const uint32_t pa = addr_to_phys(next);
     73        uint32_t pa = addr_to_phys(next);
    7774        if (pa) {
    7875                instance->next = LINK_POINTER_QH(pa);
     
    9188static inline void qh_set_element_td(qh_t *instance, td_t *td)
    9289{
    93         /* Physical address has to be below 4GB,
    94          * it is an UHCI limitation and malloc32
    95          * should guarantee this */
    96         const uint32_t pa = addr_to_phys(td);
     90        uint32_t pa = addr_to_phys(td);
    9791        if (pa) {
    9892                instance->element = LINK_POINTER_TD(pa);
  • uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c

    rf1d6866 r85ff862  
    6161 */
    6262void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
    63     bool low_speed, usb_target_t target, usb_packet_id pid, const void *buffer,
    64     const td_t *next)
     63    bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
     64    td_t *next)
    6565{
    6666        assert(instance);
     
    113113 * @return Error code.
    114114 */
    115 int td_status(const td_t *instance)
     115int td_status(td_t *instance)
    116116{
    117117        assert(instance);
     
    119119        /* This is hc internal error it should never be reported. */
    120120        if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0)
    121                 return EIO;
     121                return EAGAIN;
    122122
    123123        /* CRC or timeout error, like device not present or bad data,
     
    150150 * @param[in] instance TD structure to use.
    151151 */
    152 void td_print_status(const td_t *instance)
     152void td_print_status(td_t *instance)
    153153{
    154154        assert(instance);
  • uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h

    rf1d6866 r85ff862  
    6969#define TD_STATUS_ACTLEN_MASK 0x7ff
    7070
    71         /** Double word with USB device specific info */
     71        /* double word with USB device specific info */
    7272        volatile uint32_t device;
    7373#define TD_DEVICE_MAXLEN_POS 21
     
    8787        /* According to UHCI design guide, there is 16 bytes of
    8888         * data available here.
    89          * According to Linux kernel the hardware does not care,
    90          * memory just needs to be aligned. We don't use it anyway.
     89         * According to linux kernel the hardware does not care,
     90         * it just needs to be aligned. We don't use it anyway.
    9191         */
    9292} __attribute__((packed)) td_t;
     
    9595void td_init(td_t *instance, int error_count, size_t size, bool toggle,
    9696    bool iso, bool low_speed, usb_target_t target, usb_packet_id pid,
    97     const void *buffer, const td_t *next);
     97    void *buffer, td_t *next);
    9898
    99 int td_status(const td_t *instance);
     99int td_status(td_t *instance);
    100100
    101 void td_print_status(const td_t *instance);
     101void td_print_status(td_t *instance);
    102102/*----------------------------------------------------------------------------*/
    103103/** Helper function for parsing actual size out of TD.
     
    106106 * @return Parsed actual size.
    107107 */
    108 static inline size_t td_act_size(const td_t *instance)
     108static inline size_t td_act_size(td_t *instance)
    109109{
    110110        assert(instance);
    111111        const uint32_t s = instance->status;
    112         /* Actual size is encoded as n-1 (UHCI design guide p. 23) */
    113112        return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
    114113}
     
    120119 * false otherwise.
    121120 */
    122 static inline bool td_is_short(const td_t *instance)
     121static inline bool td_is_short(td_t *instance)
    123122{
    124123        const size_t act_size = td_act_size(instance);
     
    135134 * @return Toggle bit value.
    136135 */
    137 static inline int td_toggle(const td_t *instance)
     136static inline int td_toggle(td_t *instance)
    138137{
    139138        assert(instance);
     
    146145 * @return Active bit value.
    147146 */
    148 static inline bool td_is_active(const td_t *instance)
     147static inline bool td_is_active(td_t *instance)
    149148{
    150149        assert(instance);
  • uspace/drv/bus/usb/uhci/main.c

    rf1d6866 r85ff862  
    6464        assert(device);
    6565
    66         const int ret = device_setup_uhci(device);
     66        int ret = device_setup_uhci(device);
    6767        if (ret != EOK) {
    6868                usb_log_error("Failed to initialize UHCI driver: %s.\n",
    6969                    str_error(ret));
    70         } else {
    71                 usb_log_info("Controlling new UHCI device '%s'.\n",
    72                     device->name);
     70                return ret;
    7371        }
     72        usb_log_info("Controlling new UHCI device '%s'.\n", device->name);
    7473
    75         return ret;
     74        return EOK;
    7675}
    7776/*----------------------------------------------------------------------------*/
  • uspace/drv/bus/usb/uhci/pci.c

    rf1d6866 r85ff862  
    6161        assert(io_reg_size);
    6262        assert(irq_no);
    63 
     63       
    6464        async_sess_t *parent_sess =
    6565            devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
     
    6767        if (!parent_sess)
    6868                return ENOMEM;
    69 
     69       
    7070        hw_resource_list_t hw_resources;
    71         const int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
    72         async_hangup(parent_sess);
     71        int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
    7372        if (rc != EOK) {
     73                async_hangup(parent_sess);
    7474                return rc;
    7575        }
    76 
     76       
    7777        uintptr_t io_address = 0;
    7878        size_t io_size = 0;
    7979        bool io_found = false;
    80 
     80       
    8181        int irq = 0;
    8282        bool irq_found = false;
    83 
     83       
    8484        size_t i;
    8585        for (i = 0; i < hw_resources.count; i++) {
     
    102102                }
    103103        }
    104         free(hw_resources.resources);
    105 
     104       
     105        async_hangup(parent_sess);
     106       
    106107        if (!io_found || !irq_found)
    107108                return ENOENT;
    108 
     109       
    109110        *io_reg_address = io_address;
    110111        *io_reg_size = io_size;
    111112        *irq_no = irq;
    112 
     113       
    113114        return EOK;
    114115}
    115 /*----------------------------------------------------------------------------*/
     116
    116117/** Call the PCI driver with a request to enable interrupts
    117118 *
     
    126127        if (!parent_sess)
    127128                return ENOMEM;
    128 
     129       
    129130        const bool enabled = hw_res_enable_interrupt(parent_sess);
    130131        async_hangup(parent_sess);
    131 
     132       
    132133        return enabled ? EOK : EIO;
    133134}
    134 /*----------------------------------------------------------------------------*/
     135
    135136/** Call the PCI driver with a request to clear legacy support register
    136137 *
     
    141142{
    142143        assert(device);
    143 
     144       
    144145        async_sess_t *parent_sess =
    145146            devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
     
    147148        if (!parent_sess)
    148149                return ENOMEM;
    149 
     150       
    150151        /* See UHCI design guide for these values p.45,
    151152         * write all WC bits in USB legacy register */
    152153        const sysarg_t address = 0xc0;
    153154        const sysarg_t value = 0xaf00;
    154 
     155       
    155156        async_exch_t *exch = async_exchange_begin(parent_sess);
    156 
     157       
    157158        const int rc = async_req_3_0(exch, DEV_IFACE_ID(PCI_DEV_IFACE),
    158159            IPC_M_CONFIG_SPACE_WRITE_16, address, value);
    159 
     160       
    160161        async_exchange_end(exch);
    161162        async_hangup(parent_sess);
    162 
     163       
    163164        return rc;
    164165}
  • uspace/drv/bus/usb/uhci/root_hub.c

    rf1d6866 r85ff862  
    5050int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size)
    5151{
    52         assert(instance);
     52        int ret;
     53
    5354        assert(fun);
     55
     56        ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100);
     57        if (ret != EOK) {
     58                usb_log_error("Failed to add root hub match id: %s\n",
     59                    str_error(ret));
     60                return ret;
     61        }
    5462
    5563        /* Initialize resource structure */
     
    6270        instance->io_regs.res.io_range.endianness = LITTLE_ENDIAN;
    6371
    64         const int ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100);
    65         if (ret != EOK) {
    66                 usb_log_error("Failed to add root hub match id: %s\n",
    67                     str_error(ret));
    68         }
    69         return ret;
     72        return EOK;
    7073}
    7174/**
  • uspace/drv/bus/usb/uhci/transfer_list.c

    rf1d6866 r85ff862  
    3737#include <usb/debug.h>
    3838#include <libarch/barrier.h>
    39 
    4039#include "transfer_list.h"
     40#include "batch.h"
    4141
    4242static void transfer_list_remove_batch(
    43     transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch);
     43    transfer_list_t *instance, usb_transfer_batch_t *batch);
    4444/*----------------------------------------------------------------------------*/
    4545/** Initialize transfer list structures.
     
    106106 */
    107107void transfer_list_add_batch(
    108     transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch)
    109 {
    110         assert(instance);
    111         assert(uhci_batch);
    112         usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name,
    113             uhci_batch->usb_batch);
     108    transfer_list_t *instance, usb_transfer_batch_t *batch)
     109{
     110        assert(instance);
     111        assert(batch);
     112        usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
    114113
    115114        fibril_mutex_lock(&instance->guard);
    116115
    117         /* Assume there is nothing scheduled */
    118         qh_t *last_qh = instance->queue_head;
    119         /* There is something scheduled */
    120         if (!list_empty(&instance->batch_list)) {
    121                 last_qh = uhci_transfer_batch_from_link(
    122                     list_last(&instance->batch_list))->qh;
    123         }
     116        qh_t *last_qh = NULL;
    124117        /* Add to the hardware queue. */
    125         const uint32_t pa = addr_to_phys(uhci_batch->qh);
     118        if (list_empty(&instance->batch_list)) {
     119                /* There is nothing scheduled */
     120                last_qh = instance->queue_head;
     121        } else {
     122                /* There is something scheduled */
     123                usb_transfer_batch_t *last = usb_transfer_batch_from_link(
     124                    list_last(&instance->batch_list));
     125                last_qh = batch_qh(last);
     126        }
     127        const uint32_t pa = addr_to_phys(batch_qh(batch));
    126128        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
    127129
     
    130132
    131133        /* keep link */
    132         uhci_batch->qh->next = last_qh->next;
    133         qh_set_next_qh(last_qh, uhci_batch->qh);
     134        batch_qh(batch)->next = last_qh->next;
     135        qh_set_next_qh(last_qh, batch_qh(batch));
    134136
    135137        /* Make sure the pointer is updated */
     
    137139
    138140        /* Add to the driver's list */
    139         list_append(&uhci_batch->link, &instance->batch_list);
     141        list_append(&batch->link, &instance->batch_list);
    140142
    141143        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n",
    142             uhci_batch, USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch),
    143             instance->name);
     144            batch, USB_TRANSFER_BATCH_ARGS(*batch), instance->name);
    144145        fibril_mutex_unlock(&instance->guard);
    145146}
     
    156157
    157158        fibril_mutex_lock(&instance->guard);
    158         link_t *current = list_first(&instance->batch_list);
    159         while (current && current != &instance->batch_list.head) {
     159        link_t *current = instance->batch_list.head.next;
     160        while (current != &instance->batch_list.head) {
    160161                link_t * const next = current->next;
    161                 uhci_transfer_batch_t *batch =
    162                     uhci_transfer_batch_from_link(current);
    163 
    164                 if (uhci_transfer_batch_is_complete(batch)) {
     162                usb_transfer_batch_t *batch =
     163                    usb_transfer_batch_from_link(current);
     164
     165                if (batch_is_complete(batch)) {
    165166                        /* Save for processing */
    166167                        transfer_list_remove_batch(instance, batch);
     
    181182        while (!list_empty(&instance->batch_list)) {
    182183                link_t * const current = list_first(&instance->batch_list);
    183                 uhci_transfer_batch_t *batch =
    184                     uhci_transfer_batch_from_link(current);
     184                usb_transfer_batch_t *batch =
     185                    usb_transfer_batch_from_link(current);
    185186                transfer_list_remove_batch(instance, batch);
    186                 batch->usb_batch->error = EINTR;
    187                 uhci_transfer_batch_call_dispose(batch);
     187                usb_transfer_batch_finish_error(batch, EINTR);
    188188        }
    189189        fibril_mutex_unlock(&instance->guard);
     
    198198 */
    199199void transfer_list_remove_batch(
    200     transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch)
     200    transfer_list_t *instance, usb_transfer_batch_t *batch)
    201201{
    202202        assert(instance);
    203203        assert(instance->queue_head);
    204         assert(uhci_batch);
    205         assert(uhci_batch->qh);
     204        assert(batch);
     205        assert(batch_qh(batch));
    206206        assert(fibril_mutex_is_locked(&instance->guard));
    207207
    208         usb_log_debug2("Queue %s: removing batch(%p).\n",
    209             instance->name, uhci_batch->usb_batch);
    210 
    211         /* Assume I'm the first */
    212         const char *qpos = "FIRST";
    213         qh_t *prev_qh = instance->queue_head;
     208        usb_log_debug2(
     209            "Queue %s: removing batch(%p).\n", instance->name, batch);
     210
     211        const char *qpos = NULL;
     212        qh_t *prev_qh = NULL;
    214213        /* Remove from the hardware queue */
    215         if (list_first(&instance->batch_list) != &uhci_batch->link) {
    216                 /* There is a batch in front of me */
    217                 prev_qh =
    218                     uhci_transfer_batch_from_link(uhci_batch->link.prev)->qh;
     214        if (list_first(&instance->batch_list) == &batch->link) {
     215                /* I'm the first one here */
     216                prev_qh = instance->queue_head;
     217                qpos = "FIRST";
     218        } else {
     219                /* The thing before me is a batch too */
     220                usb_transfer_batch_t *prev =
     221                    usb_transfer_batch_from_link(batch->link.prev);
     222                prev_qh = batch_qh(prev);
    219223                qpos = "NOT FIRST";
    220224        }
    221225        assert((prev_qh->next & LINK_POINTER_ADDRESS_MASK)
    222             == addr_to_phys(uhci_batch->qh));
    223         prev_qh->next = uhci_batch->qh->next;
     226            == addr_to_phys(batch_qh(batch)));
     227        prev_qh->next = batch_qh(batch)->next;
    224228
    225229        /* Make sure the pointer is updated */
     
    227231
    228232        /* Remove from the batch list */
    229         list_remove(&uhci_batch->link);
     233        list_remove(&batch->link);
    230234        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " removed (%s) "
    231235            "from %s, next: %x.\n",
    232             uhci_batch, USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch),
    233             qpos, instance->name, uhci_batch->qh->next);
     236            batch, USB_TRANSFER_BATCH_ARGS(*batch),
     237            qpos, instance->name, batch_qh(batch)->next);
    234238}
    235239/**
  • uspace/drv/bus/usb/uhci/transfer_list.h

    rf1d6866 r85ff862  
    3636
    3737#include <fibril_synch.h>
     38#include <usb/host/batch.h>
    3839
    3940#include "hw_struct/queue_head.h"
    40 #include "uhci_batch.h"
     41
    4142/** Structure maintaining both hw queue and software list
    4243 * of currently executed transfers
     
    4546        /** Guard against multiple add/remove races */
    4647        fibril_mutex_t guard;
    47         /** UHCI hw structure representing this queue */
     48        /** UHCI hw structure represeting this queue */
    4849        qh_t *queue_head;
    4950        /** Assigned name, for nicer debug output */
     
    5758void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
    5859void transfer_list_add_batch(
    59     transfer_list_t *instance, uhci_transfer_batch_t *batch);
     60    transfer_list_t *instance, usb_transfer_batch_t *batch);
    6061void transfer_list_remove_finished(transfer_list_t *instance, list_t *done);
    6162void transfer_list_abort_all(transfer_list_t *instance);
  • uspace/drv/bus/usb/uhci/uhci.c

    rf1d6866 r85ff862  
    4141
    4242#include "uhci.h"
     43#include "iface.h"
    4344#include "pci.h"
    4445
     
    8687/** Operations supported by the HC driver */
    8788static ddf_dev_ops_t hc_ops = {
    88         .interfaces[USBHC_DEV_IFACE] = &hcd_iface, /* see iface.h/c */
     89        .interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
    8990};
    9091/*----------------------------------------------------------------------------*/
     
    99100{
    100101        assert(fun);
    101         usb_device_manager_t *manager =
    102             &dev_to_uhci(fun->dev)->hc.generic.dev_manager;
    103         const usb_address_t addr = usb_device_manager_find(manager, handle);
     102        usb_device_keeper_t *manager = &dev_to_uhci(fun->dev)->hc.manager;
     103        usb_address_t addr = usb_device_keeper_find(manager, handle);
    104104
    105105        if (addr < 0) {
     
    202202        CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n");
    203203        instance->hc_fun->ops = &hc_ops;
    204         instance->hc_fun->driver_data = &instance->hc.generic;
     204        instance->hc_fun->driver_data = &instance->hc;
    205205
    206206        instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_rh");
  • uspace/drv/bus/usb/uhci/utils/malloc32.h

    rf1d6866 r85ff862  
    5050 * @return Physical address if exists, NULL otherwise.
    5151 */
    52 static inline uintptr_t addr_to_phys(const void *addr)
     52static inline uintptr_t addr_to_phys(void *addr)
    5353{
    5454        if (addr == NULL)
     
    102102        if (free_address == 0)
    103103                return NULL;
    104         void *address = as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
     104        void *ret = as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
    105105                  AS_AREA_READ | AS_AREA_WRITE);
    106         if (address != free_address)
     106        if (ret != free_address)
    107107                return NULL;
    108         return address;
    109 }
    110 /*----------------------------------------------------------------------------*/
    111 static inline void return_page(void *page)
    112 {
    113         if (page)
    114                 as_area_destroy(page);
     108        return ret;
    115109}
    116110
  • uspace/drv/bus/usb/vhc/connhost.c

    rf1d6866 r85ff862  
    6262        VHC_DATA(vhc, fun);
    6363
    64         usb_address_t addr = usb_device_manager_get_free_address(
    65             &vhc->dev_manager, USB_SPEED_HIGH);
     64        usb_address_t addr = device_keeper_get_free_address(&vhc->dev_keeper,
     65            USB_SPEED_HIGH);
    6666        if (addr < 0) {
    6767                return addr;
     
    8888        usb_log_debug("Binding handle %" PRIun " to address %d.\n",
    8989            handle, address);
    90         usb_device_manager_bind(&vhc->dev_manager, address, handle);
     90        usb_device_keeper_bind(&vhc->dev_keeper, address, handle);
    9191
    9292        return EOK;
     
    105105        VHC_DATA(vhc, fun);
    106106        bool found =
    107             usb_device_manager_find_by_address(&vhc->dev_manager, address, handle);
     107            usb_device_keeper_find_by_address(&vhc->dev_keeper, address, handle);
    108108        return found ? EOK : ENOENT;
    109109}
     
    119119        VHC_DATA(vhc, fun);
    120120        usb_log_debug("Releasing address %d...\n", address);
    121         usb_device_manager_release(&vhc->dev_manager, address);
     121        usb_device_keeper_release(&vhc->dev_keeper, address);
    122122
    123123        return ENOTSUP;
     
    172172        VHC_DATA(vhc, fun);
    173173
     174        endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
     175            address, endpoint, direction, NULL);
     176        if (ep == NULL) {
     177                return ENOENT;
     178        }
     179
    174180        int rc = usb_endpoint_manager_unregister_ep(&vhc->ep_manager,
    175181            address, endpoint, direction);
     
    177183        return rc;
    178184}
    179 #if 0
     185
    180186/** Schedule interrupt out transfer.
    181187 *
     
    407413        return EOK;
    408414}
    409 #endif
    410 static int usb_read(ddf_fun_t *fun, usb_target_t target, uint64_t setup_buffer,
    411     uint8_t *data_buffer, size_t data_buffer_size,
    412     usbhc_iface_transfer_in_callback_t callback, void *arg)
    413 {
    414         VHC_DATA(vhc, fun);
    415 
    416         endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
    417             target.address, target.endpoint, USB_DIRECTION_IN, NULL);
    418         if (ep == NULL) {
    419                 return ENOENT;
    420         }
    421         const usb_transfer_type_t transfer_type = ep->transfer_type;
    422 
    423 
    424         vhc_transfer_t *transfer = vhc_transfer_create(target.address,
    425             target.endpoint, USB_DIRECTION_IN, transfer_type,
    426             fun, arg);
    427         if (transfer == NULL) {
    428                 return ENOMEM;
    429         }
    430         if (transfer_type == USB_TRANSFER_CONTROL) {
    431                 transfer->setup_buffer = malloc(sizeof(uint64_t));
    432                 assert(transfer->setup_buffer);
    433                 memcpy(transfer->setup_buffer, &setup_buffer, sizeof(uint64_t));
    434                 transfer->setup_buffer_size = sizeof(uint64_t);
    435         }
    436         transfer->data_buffer = data_buffer;
    437         transfer->data_buffer_size = data_buffer_size;
    438         transfer->callback_in = callback;
    439 
    440         int rc = vhc_virtdev_add_transfer(vhc, transfer);
    441         if (rc != EOK) {
    442                 free(transfer->setup_buffer);
    443                 free(transfer);
    444                 return rc;
    445         }
    446 
    447         return EOK;
    448 }
    449 
    450 static int usb_write(ddf_fun_t *fun, usb_target_t target, uint64_t setup_buffer,
    451     const uint8_t *data_buffer, size_t data_buffer_size,
    452     usbhc_iface_transfer_out_callback_t callback, void *arg)
    453 {
    454         VHC_DATA(vhc, fun);
    455 
    456         endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
    457             target.address, target.endpoint, USB_DIRECTION_OUT, NULL);
    458         if (ep == NULL) {
    459                 return ENOENT;
    460         }
    461         const usb_transfer_type_t transfer_type = ep->transfer_type;
    462 
    463 
    464         vhc_transfer_t *transfer = vhc_transfer_create(target.address,
    465             target.endpoint, USB_DIRECTION_OUT, transfer_type,
    466             fun, arg);
    467         if (transfer == NULL) {
    468                 return ENOMEM;
    469         }
    470         if (transfer_type == USB_TRANSFER_CONTROL) {
    471                 transfer->setup_buffer = malloc(sizeof(uint64_t));
    472                 assert(transfer->setup_buffer);
    473                 memcpy(transfer->setup_buffer, &setup_buffer, sizeof(uint64_t));
    474                 transfer->setup_buffer_size = sizeof(uint64_t);
    475         }
    476         transfer->data_buffer = (void*)data_buffer;
    477         transfer->data_buffer_size = data_buffer_size;
    478         transfer->callback_out = callback;
    479 
    480         int rc = vhc_virtdev_add_transfer(vhc, transfer);
    481         if (rc != EOK) {
    482                 free(transfer->setup_buffer);
    483                 free(transfer);
    484                 return rc;
    485         }
    486 
    487         return EOK;
    488 }
    489415
    490416static int tell_address(ddf_fun_t *fun, devman_handle_t handle,
     
    516442
    517443        usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle);
    518         usb_address_t addr = usb_device_manager_find(&vhc->dev_manager, handle);
     444        usb_address_t addr = usb_device_keeper_find(&vhc->dev_keeper, handle);
    519445        if (addr < 0) {
    520446                return addr;
     
    534460        .unregister_endpoint = unregister_endpoint,
    535461
    536         .write = usb_write,
    537         .read = usb_read,
     462        .interrupt_out = interrupt_out,
     463        .interrupt_in = interrupt_in,
     464
     465        .bulk_in = bulk_in,
     466        .bulk_out = bulk_out,
     467
     468        .control_write = control_write,
     469        .control_read = control_read
    538470};
    539471
  • uspace/drv/bus/usb/vhc/main.c

    rf1d6866 r85ff862  
    7373        }
    7474        data->magic = 0xDEADBEEF;
    75         rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1,
    76             bandwidth_count_usb11);
     75        rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1);
    7776        if (rc != EOK) {
    7877                usb_log_fatal("Failed to initialize endpoint manager.\n");
     
    8079                return rc;
    8180        }
    82         usb_device_manager_init(&data->dev_manager);
     81        usb_device_keeper_init(&data->dev_keeper);
    8382
    8483        ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc");
  • uspace/drv/bus/usb/vhc/vhcd.h

    rf1d6866 r85ff862  
    3939#include <usbvirt/device.h>
    4040#include <usb/host/usb_endpoint_manager.h>
    41 #include <usb/host/usb_device_manager.h>
     41#include <usb/host/device_keeper.h>
    4242#include <usbhc_iface.h>
    4343#include <async.h>
     
    6060        fibril_mutex_t guard;
    6161        usb_endpoint_manager_t ep_manager;
    62         usb_device_manager_t dev_manager;
     62        usb_device_keeper_t dev_keeper;
    6363        usbvirt_device_t *hub;
    6464        ddf_fun_t *hc_fun;
  • uspace/drv/char/ns8250/ns8250.c

    rf1d6866 r85ff862  
    5959
    6060#include <devman.h>
    61 #include <ns.h>
    6261#include <ipc/devman.h>
    63 #include <ipc/services.h>
    64 #include <ipc/irc.h>
    6562#include <device/hw_res.h>
    6663#include <ipc/serial_ctl.h>
     
    412409static int ns8250_interrupt_enable(ns8250_t *ns)
    413410{
    414         /*
    415          * Enable interrupt using IRC service.
    416          * TODO: This is a temporary solution until the device framework
    417          * takes care of this itself.
    418          */
    419         async_sess_t *irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
    420             SERVICE_IRC, 0, 0);
    421         if (!irc_sess) {
    422                 return EIO;
    423         }
    424 
    425         async_exch_t *exch = async_exchange_begin(irc_sess);
    426         if (!exch) {
    427                 return EIO;
    428         }
    429         async_msg_1(exch, IRC_ENABLE_INTERRUPT, ns->irq);
    430         async_exchange_end(exch);
    431 
    432411        /* Enable interrupt on the serial port. */
    433412        ns8250_port_interrupts_enable(ns->port);
  • uspace/lib/c/Makefile

    rf1d6866 r85ff862  
    6363        generic/as.c \
    6464        generic/cap.c \
    65         generic/cfg.c \
    6665        generic/clipboard.c \
    6766        generic/devman.c \
  • uspace/lib/c/generic/adt/hash_table.c

    rf1d6866 r85ff862  
    152152       
    153153        if (keys == h->max_keys) {
     154                link_t *cur;
     155               
    154156                /*
    155157                 * All keys are known, hash_table_find() can be used to find the
     
    157159                 */
    158160               
    159                 link_t *cur = hash_table_find(h, key);
     161                cur = hash_table_find(h, key);
    160162                if (cur) {
    161163                        list_remove(cur);
     
    172174        hash_index_t chain;
    173175        for (chain = 0; chain < h->entries; chain++) {
    174                 for (link_t *cur = h->entry[chain].head.next;
    175                     cur != &h->entry[chain].head;
     176                link_t *cur;
     177               
     178                for (cur = h->entry[chain].head.next; cur != &h->entry[chain].head;
    176179                    cur = cur->next) {
    177180                        if (h->op->compare(key, keys, cur)) {
  • uspace/lib/c/generic/as.c

    rf1d6866 r85ff862  
    123123 * @retval ENOENT Mapping not found.
    124124 */
    125 int as_get_physical_mapping(const void *address, uintptr_t *frame)
     125int as_get_physical_mapping(void *address, uintptr_t *frame)
    126126{
    127127        uintptr_t tmp_frame;
  • uspace/lib/c/generic/io/io.c

    rf1d6866 r85ff862  
    418418
    419419        bytes_used = stream->buf_head - stream->buf_tail;
     420        if (bytes_used == 0)
     421                return;
    420422
    421423        /* If buffer has prefetched read data, we need to seek back. */
    422         if (bytes_used > 0 && stream->buf_state == _bs_read)
     424        if (stream->buf_state == _bs_read)
    423425                lseek(stream->fd, - (ssize_t) bytes_used, SEEK_CUR);
    424426
    425427        /* If buffer has unwritten data, we need to write them out. */
    426         if (bytes_used > 0 && stream->buf_state == _bs_write)
     428        if (stream->buf_state == _bs_write)
    427429                (void) _fwrite(stream->buf_tail, 1, bytes_used, stream);
    428430
  • uspace/lib/c/generic/ns.c

    rf1d6866 r85ff862  
    5252{
    5353        async_exch_t *exch = async_exchange_begin(session_ns);
    54         if (!exch)
    55                 return NULL;
    5654        async_sess_t *sess =
    5755            async_connect_me_to(mgmt, exch, service, arg2, arg3);
    5856        async_exchange_end(exch);
    59 
    60         if (!sess)
    61                 return NULL;
    6257       
    6358        /*
  • uspace/lib/c/include/adt/list.h

    rf1d6866 r85ff862  
    173173 *
    174174 */
    175 static inline int list_empty(const list_t *list)
     175static inline int list_empty(list_t *list)
    176176{
    177177        return (list->head.next == &list->head);
     
    186186 *
    187187 */
    188 static inline link_t *list_first(const list_t *list)
     188static inline link_t *list_first(list_t *list)
    189189{
    190190        return ((list->head.next == &list->head) ? NULL : list->head.next);
  • uspace/lib/c/include/as.h

    rf1d6866 r85ff862  
    6060extern void *set_maxheapsize(size_t);
    6161extern void *as_get_mappable_page(size_t);
    62 extern int as_get_physical_mapping(const void *, uintptr_t *);
     62extern int as_get_physical_mapping(void *, uintptr_t *);
    6363
    6464#endif
  • uspace/lib/c/include/ipc/loc.h

    rf1d6866 r85ff862  
    9797
    9898#endif
    99 
    100 /** @}
    101  */
  • uspace/lib/drv/generic/dev_iface.c

    rf1d6866 r85ff862  
    4646#include "remote_pci.h"
    4747
     48#include <stdio.h>
     49
    4850static iface_dipatch_table_t remote_ifaces = {
    4951        .ifaces = {
     
    6668get_remote_method(remote_iface_t *rem_iface, sysarg_t iface_method_idx)
    6769{
    68         if (iface_method_idx >= rem_iface->method_count)
     70        if (iface_method_idx >= rem_iface->method_count) {
    6971                return NULL;
    70        
     72        }
     73
    7174        return rem_iface->methods[iface_method_idx];
    7275}
  • uspace/lib/drv/generic/driver.c

    rf1d6866 r85ff862  
    271271       
    272272        devman_handle_t dev_handle = IPC_GET_ARG1(*icall);
    273         devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall);
     273        devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall);
    274274       
    275275        ddf_dev_t *dev = create_device();
  • uspace/lib/drv/generic/remote_usbhc.c

    rf1d6866 r85ff862  
    4141
    4242#define USB_MAX_PAYLOAD_SIZE 1020
    43 
     43#define HACK_MAX_PACKET_SIZE 8
     44#define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4
     45
     46static void remote_usbhc_interrupt_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     47static void remote_usbhc_interrupt_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     48static void remote_usbhc_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     49static void remote_usbhc_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     50static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     51static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    4452static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    4553static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     
    4856static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    4957static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    50 static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    51 static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5258//static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5359
    5460/** Remote USB host controller interface operations. */
    55 static remote_iface_func_ptr_t remote_usbhc_iface_ops[] = {
    56         [IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address,
    57         [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address,
    58         [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_find_by_address,
    59         [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address,
    60 
    61         [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint,
    62         [IPC_M_USBHC_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint,
    63 
    64         [IPC_M_USBHC_READ] = remote_usbhc_read,
    65         [IPC_M_USBHC_WRITE] = remote_usbhc_write,
     61static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
     62        remote_usbhc_request_address,
     63        remote_usbhc_bind_address,
     64        remote_usbhc_find_by_address,
     65        remote_usbhc_release_address,
     66
     67        remote_usbhc_interrupt_out,
     68        remote_usbhc_interrupt_in,
     69
     70        remote_usbhc_bulk_out,
     71        remote_usbhc_bulk_in,
     72
     73        remote_usbhc_control_write,
     74        remote_usbhc_control_read,
     75
     76        remote_usbhc_register_endpoint,
     77        remote_usbhc_unregister_endpoint
    6678};
    6779
     
    7890        ipc_callid_t data_caller;
    7991        void *buffer;
     92        void *setup_packet;
    8093        size_t size;
    8194} async_transaction_t;
     
    8598        if (trans == NULL) {
    8699                return;
     100        }
     101
     102        if (trans->setup_packet != NULL) {
     103                free(trans->setup_packet);
    87104        }
    88105        if (trans->buffer != NULL) {
     
    103120        trans->data_caller = 0;
    104121        trans->buffer = NULL;
     122        trans->setup_packet = NULL;
    105123        trans->size = 0;
    106124
     
    117135                return;
    118136        }
    119 
     137       
    120138        usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
    121139
     
    221239        async_transaction_destroy(trans);
    222240}
     241
     242/** Process an outgoing transfer (both OUT and SETUP).
     243 *
     244 * @param device Target device.
     245 * @param callid Initiating caller.
     246 * @param call Initiating call.
     247 * @param transfer_func Transfer function (might be NULL).
     248 */
     249static void remote_usbhc_out_transfer(ddf_fun_t *fun,
     250    ipc_callid_t callid, ipc_call_t *call,
     251    usbhc_iface_transfer_out_t transfer_func)
     252{
     253        if (!transfer_func) {
     254                async_answer_0(callid, ENOTSUP);
     255                return;
     256        }
     257
     258        usb_target_t target = {
     259                .address = DEV_IPC_GET_ARG1(*call),
     260                .endpoint = DEV_IPC_GET_ARG2(*call)
     261        };
     262
     263        size_t len = 0;
     264        void *buffer = NULL;
     265
     266        int rc = async_data_write_accept(&buffer, false,
     267            1, USB_MAX_PAYLOAD_SIZE,
     268            0, &len);
     269
     270        if (rc != EOK) {
     271                async_answer_0(callid, rc);
     272                return;
     273        }
     274
     275        async_transaction_t *trans = async_transaction_create(callid);
     276        if (trans == NULL) {
     277                if (buffer != NULL) {
     278                        free(buffer);
     279                }
     280                async_answer_0(callid, ENOMEM);
     281                return;
     282        }
     283
     284        trans->buffer = buffer;
     285        trans->size = len;
     286
     287        rc = transfer_func(fun, target,
     288            buffer, len,
     289            callback_out, trans);
     290
     291        if (rc != EOK) {
     292                async_answer_0(callid, rc);
     293                async_transaction_destroy(trans);
     294        }
     295}
     296
     297/** Process an incoming transfer.
     298 *
     299 * @param device Target device.
     300 * @param callid Initiating caller.
     301 * @param call Initiating call.
     302 * @param transfer_func Transfer function (might be NULL).
     303 */
     304static void remote_usbhc_in_transfer(ddf_fun_t *fun,
     305    ipc_callid_t callid, ipc_call_t *call,
     306    usbhc_iface_transfer_in_t transfer_func)
     307{
     308        if (!transfer_func) {
     309                async_answer_0(callid, ENOTSUP);
     310                return;
     311        }
     312
     313        usb_target_t target = {
     314                .address = DEV_IPC_GET_ARG1(*call),
     315                .endpoint = DEV_IPC_GET_ARG2(*call)
     316        };
     317
     318        size_t len;
     319        ipc_callid_t data_callid;
     320        if (!async_data_read_receive(&data_callid, &len)) {
     321                async_answer_0(callid, EPARTY);
     322                return;
     323        }
     324
     325        async_transaction_t *trans = async_transaction_create(callid);
     326        if (trans == NULL) {
     327                async_answer_0(data_callid, ENOMEM);
     328                async_answer_0(callid, ENOMEM);
     329                return;
     330        }
     331        trans->data_caller = data_callid;
     332        trans->buffer = malloc(len);
     333        trans->size = len;
     334
     335        int rc = transfer_func(fun, target,
     336            trans->buffer, len,
     337            callback_in, trans);
     338
     339        if (rc != EOK) {
     340                async_answer_0(data_callid, rc);
     341                async_answer_0(callid, rc);
     342                async_transaction_destroy(trans);
     343        }
     344}
     345
     346void remote_usbhc_interrupt_out(ddf_fun_t *fun, void *iface,
     347    ipc_callid_t callid, ipc_call_t *call)
     348{
     349        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     350        assert(usb_iface != NULL);
     351
     352        return remote_usbhc_out_transfer(fun, callid, call,
     353            usb_iface->interrupt_out);
     354}
     355
     356void remote_usbhc_interrupt_in(ddf_fun_t *fun, void *iface,
     357    ipc_callid_t callid, ipc_call_t *call)
     358{
     359        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     360        assert(usb_iface != NULL);
     361
     362        return remote_usbhc_in_transfer(fun, callid, call,
     363            usb_iface->interrupt_in);
     364}
     365
     366void remote_usbhc_bulk_out(ddf_fun_t *fun, void *iface,
     367    ipc_callid_t callid, ipc_call_t *call)
     368{
     369        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     370        assert(usb_iface != NULL);
     371
     372        return remote_usbhc_out_transfer(fun, callid, call,
     373            usb_iface->bulk_out);
     374}
     375
     376void remote_usbhc_bulk_in(ddf_fun_t *fun, void *iface,
     377    ipc_callid_t callid, ipc_call_t *call)
     378{
     379        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     380        assert(usb_iface != NULL);
     381
     382        return remote_usbhc_in_transfer(fun, callid, call,
     383            usb_iface->bulk_in);
     384}
     385
     386void remote_usbhc_control_write(ddf_fun_t *fun, void *iface,
     387ipc_callid_t callid, ipc_call_t *call)
     388{
     389        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     390        assert(usb_iface != NULL);
     391
     392        if (!usb_iface->control_write) {
     393                async_answer_0(callid, ENOTSUP);
     394                return;
     395        }
     396
     397        usb_target_t target = {
     398                .address = DEV_IPC_GET_ARG1(*call),
     399                .endpoint = DEV_IPC_GET_ARG2(*call)
     400        };
     401        size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);
     402
     403        int rc;
     404
     405        void *setup_packet = NULL;
     406        void *data_buffer = NULL;
     407        size_t setup_packet_len = 0;
     408
     409        rc = async_data_write_accept(&setup_packet, false,
     410            1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
     411        if (rc != EOK) {
     412                async_answer_0(callid, rc);
     413                return;
     414        }
     415
     416        if (data_buffer_len > 0) {
     417                rc = async_data_write_accept(&data_buffer, false,
     418                    1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);
     419                if (rc != EOK) {
     420                        async_answer_0(callid, rc);
     421                        free(setup_packet);
     422                        return;
     423                }
     424        }
     425
     426        async_transaction_t *trans = async_transaction_create(callid);
     427        if (trans == NULL) {
     428                async_answer_0(callid, ENOMEM);
     429                free(setup_packet);
     430                free(data_buffer);
     431                return;
     432        }
     433        trans->setup_packet = setup_packet;
     434        trans->buffer = data_buffer;
     435        trans->size = data_buffer_len;
     436
     437        rc = usb_iface->control_write(fun, target,
     438            setup_packet, setup_packet_len,
     439            data_buffer, data_buffer_len,
     440            callback_out, trans);
     441
     442        if (rc != EOK) {
     443                async_answer_0(callid, rc);
     444                async_transaction_destroy(trans);
     445        }
     446}
     447
     448
     449void remote_usbhc_control_read(ddf_fun_t *fun, void *iface,
     450ipc_callid_t callid, ipc_call_t *call)
     451{
     452        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     453        assert(usb_iface != NULL);
     454
     455        if (!usb_iface->control_read) {
     456                async_answer_0(callid, ENOTSUP);
     457                return;
     458        }
     459
     460        usb_target_t target = {
     461                .address = DEV_IPC_GET_ARG1(*call),
     462                .endpoint = DEV_IPC_GET_ARG2(*call)
     463        };
     464
     465        int rc;
     466
     467        void *setup_packet = NULL;
     468        size_t setup_packet_len = 0;
     469        size_t data_len = 0;
     470
     471        rc = async_data_write_accept(&setup_packet, false,
     472            1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
     473        if (rc != EOK) {
     474                async_answer_0(callid, rc);
     475                return;
     476        }
     477
     478        ipc_callid_t data_callid;
     479        if (!async_data_read_receive(&data_callid, &data_len)) {
     480                async_answer_0(callid, EPARTY);
     481                free(setup_packet);
     482                return;
     483        }
     484
     485        async_transaction_t *trans = async_transaction_create(callid);
     486        if (trans == NULL) {
     487                async_answer_0(data_callid, ENOMEM);
     488                async_answer_0(callid, ENOMEM);
     489                free(setup_packet);
     490                return;
     491        }
     492        trans->data_caller = data_callid;
     493        trans->setup_packet = setup_packet;
     494        trans->size = data_len;
     495        trans->buffer = malloc(data_len);
     496        if (trans->buffer == NULL) {
     497                async_answer_0(data_callid, ENOMEM);
     498                async_answer_0(callid, ENOMEM);
     499                async_transaction_destroy(trans);
     500                return;
     501        }
     502
     503        rc = usb_iface->control_read(fun, target,
     504            setup_packet, setup_packet_len,
     505            trans->buffer, trans->size,
     506            callback_in, trans);
     507
     508        if (rc != EOK) {
     509                async_answer_0(data_callid, rc);
     510                async_answer_0(callid, rc);
     511                async_transaction_destroy(trans);
     512        }
     513}
     514
    223515
    224516void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
     
    243535        type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8)
    244536
    245         const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
     537        _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1);
     538        _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1);
    246539
    247540        _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2);
     
    258551#undef _INIT_FROM_LOW_DATA3
    259552
    260         int rc = usb_iface->register_endpoint(fun, target.address, speed,
    261             target.endpoint, transfer_type, direction, max_packet_size, interval);
     553        int rc = usb_iface->register_endpoint(fun, address, speed, endpoint,
     554            transfer_type, direction, max_packet_size, interval);
    262555
    263556        async_answer_0(callid, rc);
    264557}
     558
    265559
    266560void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,
     
    284578}
    285579
    286 void remote_usbhc_read(
    287     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    288 {
    289         assert(fun);
    290         assert(iface);
    291         assert(call);
    292 
    293         const usbhc_iface_t *hc_iface = iface;
    294 
    295         if (!hc_iface->read) {
    296                 async_answer_0(callid, ENOTSUP);
    297                 return;
    298         }
    299 
    300         const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
    301         const uint64_t setup =
    302             ((uint64_t)DEV_IPC_GET_ARG2(*call)) |
    303             (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32);
    304 
    305         async_transaction_t *trans = async_transaction_create(callid);
    306         if (trans == NULL) {
    307                 async_answer_0(callid, ENOMEM);
    308                 return;
    309         }
    310 
    311         if (!async_data_read_receive(&trans->data_caller, &trans->size)) {
    312                 async_answer_0(callid, EPARTY);
    313                 return;
    314         }
    315 
    316         trans->buffer = malloc(trans->size);
    317         if (trans->buffer == NULL) {
    318                 async_answer_0(trans->data_caller, ENOMEM);
    319                 async_answer_0(callid, ENOMEM);
    320                 async_transaction_destroy(trans);
    321         }
    322 
    323         const int rc = hc_iface->read(
    324             fun, target, setup, trans->buffer, trans->size, callback_in, trans);
    325 
    326         if (rc != EOK) {
    327                 async_answer_0(trans->data_caller, rc);
    328                 async_answer_0(callid, rc);
    329                 async_transaction_destroy(trans);
    330         }
    331 }
    332 
    333 void remote_usbhc_write(
    334     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    335 {
    336         assert(fun);
    337         assert(iface);
    338         assert(call);
    339 
    340         const usbhc_iface_t *hc_iface = iface;
    341 
    342         if (!hc_iface->write) {
    343                 async_answer_0(callid, ENOTSUP);
    344                 return;
    345         }
    346 
    347         const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
    348         const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call);
    349         const uint64_t setup =
    350             ((uint64_t)DEV_IPC_GET_ARG3(*call)) |
    351             (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32);
    352 
    353         async_transaction_t *trans = async_transaction_create(callid);
    354         if (trans == NULL) {
    355                 async_answer_0(callid, ENOMEM);
    356                 return;
    357         }
    358 
    359         if (data_buffer_len > 0) {
    360                 int rc = async_data_write_accept(&trans->buffer, false,
    361                     1, USB_MAX_PAYLOAD_SIZE,
    362                     0, &trans->size);
    363 
    364                 if (rc != EOK) {
    365                         async_answer_0(callid, rc);
    366                         async_transaction_destroy(trans);
    367                         return;
    368                 }
    369         }
    370 
    371         int rc = hc_iface->write(
    372             fun, target, setup, trans->buffer, trans->size, callback_out, trans);
    373 
    374         if (rc != EOK) {
    375                 async_answer_0(callid, rc);
    376                 async_transaction_destroy(trans);
    377         }
    378 }
    379 
    380580
    381581/**
  • uspace/lib/drv/include/usbhc_iface.h

    rf1d6866 r85ff862  
    123123        IPC_M_USBHC_RELEASE_ADDRESS,
    124124
     125
     126        /** Send interrupt data to device.
     127         * See explanation at usb_iface_funcs_t (OUT transaction).
     128         */
     129        IPC_M_USBHC_INTERRUPT_OUT,
     130
     131        /** Get interrupt data from device.
     132         * See explanation at usb_iface_funcs_t (IN transaction).
     133         */
     134        IPC_M_USBHC_INTERRUPT_IN,
     135
     136        /** Send bulk data to device.
     137         * See explanation at usb_iface_funcs_t (OUT transaction).
     138         */
     139        IPC_M_USBHC_BULK_OUT,
     140
     141        /** Get bulk data from device.
     142         * See explanation at usb_iface_funcs_t (IN transaction).
     143         */
     144        IPC_M_USBHC_BULK_IN,
     145
     146        /** Issue control WRITE transfer.
     147         * See explanation at usb_iface_funcs_t (OUT transaction) for
     148         * call parameters.
     149         * This call is immediately followed by two IPC data writes
     150         * from the caller (setup packet and actual data).
     151         */
     152        IPC_M_USBHC_CONTROL_WRITE,
     153
     154        /** Issue control READ transfer.
     155         * See explanation at usb_iface_funcs_t (IN transaction) for
     156         * call parameters.
     157         * This call is immediately followed by IPC data write from the caller
     158         * (setup packet) and IPC data read (buffer that was read).
     159         */
     160        IPC_M_USBHC_CONTROL_READ,
     161
    125162        /** Register endpoint attributes at host controller.
    126163         * This is used to reserve portion of USB bandwidth.
     
    148185         * - ENOENT - unknown endpoint
    149186         */
    150         IPC_M_USBHC_UNREGISTER_ENDPOINT,
    151 
    152         /** Get data from device.
    153          * See explanation at usb_iface_funcs_t (IN transaction).
    154          */
    155         IPC_M_USBHC_READ,
    156 
    157         /** Send data to device.
    158          * See explanation at usb_iface_funcs_t (OUT transaction).
    159          */
    160         IPC_M_USBHC_WRITE,
     187        IPC_M_USBHC_UNREGISTER_ENDPOINT
    161188} usbhc_iface_funcs_t;
    162189
    163190/** Callback for outgoing transfer. */
    164 typedef void (*usbhc_iface_transfer_out_callback_t)(ddf_fun_t *, int, void *);
     191typedef void (*usbhc_iface_transfer_out_callback_t)(ddf_fun_t *,
     192    int, void *);
    165193
    166194/** Callback for incoming transfer. */
    167195typedef void (*usbhc_iface_transfer_in_callback_t)(ddf_fun_t *,
    168196    int, size_t, void *);
     197
     198
     199/** Out transfer processing function prototype. */
     200typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t,
     201    void *, size_t,
     202    usbhc_iface_transfer_out_callback_t, void *);
     203
     204/** Setup transfer processing function prototype. @deprecated */
     205typedef usbhc_iface_transfer_out_t usbhc_iface_transfer_setup_t;
     206
     207/** In transfer processing function prototype. */
     208typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t,
     209    void *, size_t,
     210    usbhc_iface_transfer_in_callback_t, void *);
    169211
    170212/** USB host controller communication interface. */
     
    181223            usb_direction_t);
    182224
    183         int (*read)(ddf_fun_t *, usb_target_t, uint64_t, uint8_t *, size_t,
     225        usbhc_iface_transfer_out_t interrupt_out;
     226        usbhc_iface_transfer_in_t interrupt_in;
     227
     228        usbhc_iface_transfer_out_t bulk_out;
     229        usbhc_iface_transfer_in_t bulk_in;
     230
     231        int (*control_write)(ddf_fun_t *, usb_target_t,
     232            void *, size_t, void *, size_t,
     233            usbhc_iface_transfer_out_callback_t, void *);
     234
     235        int (*control_read)(ddf_fun_t *, usb_target_t,
     236            void *, size_t, void *, size_t,
    184237            usbhc_iface_transfer_in_callback_t, void *);
    185 
    186         int (*write)(ddf_fun_t *, usb_target_t, uint64_t, const uint8_t *,
    187             size_t, usbhc_iface_transfer_out_callback_t, void *);
    188238} usbhc_iface_t;
    189239
  • uspace/lib/usb/include/usb/hc.h

    rf1d6866 r85ff862  
    6262    devman_handle_t *);
    6363
    64 usb_address_t usb_hc_get_address_by_handle(devman_handle_t);
     64int usb_hc_get_address_by_handle(devman_handle_t);
    6565
    6666int usb_hc_find(devman_handle_t, devman_handle_t *);
  • uspace/lib/usb/include/usb/usb.h

    rf1d6866 r85ff862  
    3636#define LIBUSB_USB_H_
    3737
    38 #include <bool.h>
    3938#include <sys/types.h>
    4039#include <byteorder.h>
     
    106105 * Negative values could be used to indicate error.
    107106 */
    108 typedef int16_t usb_address_t;
     107typedef int usb_address_t;
    109108
    110109/** Default USB address. */
     
    116115 * Negative values could be used to indicate error.
    117116 */
    118 typedef int16_t usb_endpoint_t;
     117typedef int usb_endpoint_t;
    119118
    120119/** Maximum endpoint number in USB 1.1.
     
    126125 * Pair address + endpoint is identification of transaction recipient.
    127126 */
    128 typedef union {
    129         struct {
    130                 usb_address_t address;
    131                 usb_endpoint_t endpoint;
    132         } __attribute__((packed));
    133         uint32_t packed;
     127typedef struct {
     128        usb_address_t address;
     129        usb_endpoint_t endpoint;
    134130} usb_target_t;
    135 
    136 /** Check USB target for allowed values (address and endpoint).
    137  *
    138  * @param target.
    139  * @return True, if values are wihtin limits, false otherwise.
    140  */
    141 static inline bool usb_target_is_valid(usb_target_t target)
    142 {
    143         return !(target.endpoint > 15 || target.endpoint < 0
    144             || target.address >= USB11_ADDRESS_MAX || target.address < 0);
    145 }
    146131
    147132/** Compare USB targets (addresses and endpoints).
  • uspace/lib/usbdev/src/pipesinit.c

    rf1d6866 r85ff862  
    486486                return EBADF;
    487487       
    488         const usb_target_t target =
    489             {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    490488#define _PACK2(high, low) (((high) << 16) + (low))
    491489#define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low))
     
    493491        async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
    494492        int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    495             IPC_M_USBHC_REGISTER_ENDPOINT, target.packed,
     493            IPC_M_USBHC_REGISTER_ENDPOINT,
     494            _PACK2(pipe->wire->address, pipe->endpoint_no),
    496495            _PACK3(speed, pipe->transfer_type, pipe->direction),
    497496            _PACK2(pipe->max_packet_size, interval));
  • uspace/lib/usbdev/src/pipesio.c

    rf1d6866 r85ff862  
    6565    void *buffer, size_t size, size_t *size_transfered)
    6666{
    67         /* Only interrupt and bulk transfers are supported */
    68         if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    69             pipe->transfer_type != USB_TRANSFER_BULK)
    70             return ENOTSUP;
    71 
    72         const usb_target_t target =
    73             {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
     67        /*
     68         * Get corresponding IPC method.
     69         * In future, replace with static array of mappings
     70         * transfer type -> method.
     71         */
     72        usbhc_iface_funcs_t ipc_method;
     73        switch (pipe->transfer_type) {
     74                case USB_TRANSFER_INTERRUPT:
     75                        ipc_method = IPC_M_USBHC_INTERRUPT_IN;
     76                        break;
     77                case USB_TRANSFER_BULK:
     78                        ipc_method = IPC_M_USBHC_BULK_IN;
     79                        break;
     80                default:
     81                        return ENOTSUP;
     82        }
    7483       
    7584        /* Ensure serialization over the phone. */
     
    8089         * Make call identifying target USB device and type of transfer.
    8190         */
    82         aid_t opening_request = async_send_2(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    83             IPC_M_USBHC_READ, target.packed, NULL);
     91        aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     92            ipc_method, pipe->wire->address, pipe->endpoint_no, NULL);
    8493       
    8594        if (opening_request == 0) {
     
    204213    void *buffer, size_t size)
    205214{
    206         /* Only interrupt and bulk transfers are supported */
    207         if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    208             pipe->transfer_type != USB_TRANSFER_BULK)
    209             return ENOTSUP;
    210 
    211         const usb_target_t target =
    212             {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
     215        /*
     216         * Get corresponding IPC method.
     217         * In future, replace with static array of mappings
     218         * transfer type -> method.
     219         */
     220        usbhc_iface_funcs_t ipc_method;
     221        switch (pipe->transfer_type) {
     222                case USB_TRANSFER_INTERRUPT:
     223                        ipc_method = IPC_M_USBHC_INTERRUPT_OUT;
     224                        break;
     225                case USB_TRANSFER_BULK:
     226                        ipc_method = IPC_M_USBHC_BULK_OUT;
     227                        break;
     228                default:
     229                        return ENOTSUP;
     230        }
    213231
    214232        /* Ensure serialization over the phone. */
     
    220238         */
    221239        aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    222             IPC_M_USBHC_WRITE, target.packed, size, NULL);
     240            ipc_method, pipe->wire->address, pipe->endpoint_no, NULL);
    223241       
    224242        if (opening_request == 0) {
     
    334352        pipe_start_transaction(pipe);
    335353
    336         const usb_target_t target =
    337             {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    338 
    339         assert(setup_buffer_size == 8);
    340         uint64_t setup_packet;
    341         memcpy(&setup_packet, setup_buffer, 8);
    342354        /*
    343355         * Make call identifying target USB device and control transfer type.
    344356         */
    345357        async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    346         aid_t opening_request = async_send_4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    347             IPC_M_USBHC_READ, target.packed,
    348             (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL);
    349 
     358        aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     359            IPC_M_USBHC_CONTROL_READ, pipe->wire->address, pipe->endpoint_no,
     360            NULL);
     361       
    350362        if (opening_request == 0) {
    351363                async_exchange_end(exch);
    352364                return ENOMEM;
    353365        }
    354 
     366       
     367        /*
     368         * Send the setup packet.
     369         */
     370        int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
     371        if (rc != EOK) {
     372                async_exchange_end(exch);
     373                pipe_end_transaction(pipe);
     374                async_wait_for(opening_request, NULL);
     375                return rc;
     376        }
     377       
    355378        /*
    356379         * Retrieve the data.
     
    475498        pipe_start_transaction(pipe);
    476499
    477         const usb_target_t target =
    478             {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    479         assert(setup_buffer_size == 8);
    480         uint64_t setup_packet;
    481         memcpy(&setup_packet, setup_buffer, 8);
    482 
    483500        /*
    484501         * Make call identifying target USB device and control transfer type.
    485502         */
    486503        async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    487         aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    488             IPC_M_USBHC_WRITE, target.packed, data_buffer_size,
    489             (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL);
     504        aid_t opening_request = async_send_4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     505            IPC_M_USBHC_CONTROL_WRITE, pipe->wire->address, pipe->endpoint_no,
     506            data_buffer_size, NULL);
    490507       
    491508        if (opening_request == 0) {
     
    494511                return ENOMEM;
    495512        }
    496 
     513       
     514        /*
     515         * Send the setup packet.
     516         */
     517        int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
     518        if (rc != EOK) {
     519                async_exchange_end(exch);
     520                pipe_end_transaction(pipe);
     521                async_wait_for(opening_request, NULL);
     522                return rc;
     523        }
     524       
    497525        /*
    498526         * Send the data (if any).
    499527         */
    500528        if (data_buffer_size > 0) {
    501                 int rc = async_data_write_start(exch, data_buffer, data_buffer_size);
     529                rc = async_data_write_start(exch, data_buffer, data_buffer_size);
    502530               
    503531                /* All data sent, pipe can be released. */
  • uspace/lib/usbhost/Makefile

    rf1d6866 r85ff862  
    3232        -I$(LIBUSB_PREFIX)/include \
    3333        -I$(LIBDRV_PREFIX)/include \
    34         -Iinclude 
     34        -Iinclude
    3535
    3636SOURCES = \
     37        src/batch.c \
     38        src/device_keeper.c \
    3739        src/endpoint.c \
    38         src/iface.c \
    39         src/usb_device_manager.c \
    40         src/usb_endpoint_manager.c \
    41         src/usb_transfer_batch.c
     40        src/usb_endpoint_manager.c
    4241
    4342include $(USPACE_PREFIX)/Makefile.common
  • uspace/lib/usbhost/include/usb/host/endpoint.h

    rf1d6866 r85ff862  
    5454        fibril_condvar_t avail;
    5555        volatile bool active;
    56         void (*destroy_hook)(struct endpoint *);
    5756        struct {
    5857                void *data;
     
    6968
    7069void endpoint_set_hc_data(endpoint_t *instance,
    71     void *data, void (*destroy_hook)(endpoint_t *),
    72     int (*toggle_get)(void *), void (*toggle_set)(void *, int));
     70    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int));
    7371
    7472void endpoint_clear_hc_data(endpoint_t *instance);
  • uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h

    rf1d6866 r85ff862  
    3838 */
    3939#ifndef LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H
    40 #define LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H
     40#define LIBUSBHOST_HOST_YSB_ENDPOINT_MANAGER_H
    4141
    4242#include <stdlib.h>
     
    5252        hash_table_t ep_table;
    5353        fibril_mutex_t guard;
     54        fibril_condvar_t change;
    5455        size_t free_bw;
    55         size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t);
    5656} usb_endpoint_manager_t;
    5757
     
    6060
    6161int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
    62     size_t available_bandwidth,
    63     size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t));
     62    size_t available_bandwidth);
    6463
    6564void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance);
     
    7877    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);
    7978
    80 /** Wrapper combining allocation and insertion */
    8179static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,
    8280    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
  • uspace/lib/usbhost/src/endpoint.c

    rf1d6866 r85ff862  
    5353                instance->toggle = 0;
    5454                instance->active = false;
    55                 instance->destroy_hook = NULL;
    56                 instance->hc_data.data = NULL;
    57                 instance->hc_data.toggle_get = NULL;
    58                 instance->hc_data.toggle_set = NULL;
    5955                fibril_mutex_initialize(&instance->guard);
    6056                fibril_condvar_initialize(&instance->avail);
     
    6864        assert(instance);
    6965        assert(!instance->active);
    70         if (instance->hc_data.data) {
    71                 assert(instance->destroy_hook);
    72                 instance->destroy_hook(instance);
    73         }
    7466        free(instance);
    7567}
    7668/*----------------------------------------------------------------------------*/
    7769void endpoint_set_hc_data(endpoint_t *instance,
    78     void *data, void (*destroy_hook)(endpoint_t *),
    79     int (*toggle_get)(void *), void (*toggle_set)(void *, int))
     70    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
    8071{
    8172        assert(instance);
    82         instance->destroy_hook = destroy_hook;
    8373        instance->hc_data.data = data;
    8474        instance->hc_data.toggle_get = toggle_get;
     
    8979{
    9080        assert(instance);
    91         instance->destroy_hook = NULL;
    9281        instance->hc_data.data = NULL;
    9382        instance->hc_data.toggle_get = NULL;
  • uspace/lib/usbhost/src/usb_endpoint_manager.c

    rf1d6866 r85ff862  
    4545static hash_index_t node_hash(unsigned long key[])
    4646{
    47         /* USB endpoints use 4 bits, thus ((key[0] << 4) | key[1])
    48          * produces unique value for every address.endpoint pair */
    49         return ((key[0] << 4) | key[1]) % BUCKET_COUNT;
     47        hash_index_t hash = 0;
     48        unsigned i = 0;
     49        for (;i < MAX_KEYS; ++i) {
     50                hash ^= key[i];
     51        }
     52        hash %= BUCKET_COUNT;
     53        return hash;
    5054}
    5155/*----------------------------------------------------------------------------*/
     
    5963        switch (keys) {
    6064        case 3:
    61                 match = match &&
    62                     ((key[2] == node->ep->direction)
    63                     || (node->ep->direction == USB_DIRECTION_BOTH));
     65                match = match && (key[2] == node->ep->direction);
    6466        case 2:
    6567                match = match && (key[1] == (unsigned long)node->ep->endpoint);
     
    138140/*----------------------------------------------------------------------------*/
    139141int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
    140     size_t available_bandwidth,
    141     size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t))
     142    size_t available_bandwidth)
    142143{
    143144        assert(instance);
    144145        fibril_mutex_initialize(&instance->guard);
     146        fibril_condvar_initialize(&instance->change);
    145147        instance->free_bw = available_bandwidth;
    146         instance->bw_count = bw_count;
    147         const bool ht =
     148        bool ht =
    148149            hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op);
    149150        return ht ? EOK : ENOMEM;
     
    158159    endpoint_t *ep, size_t data_size)
    159160{
    160         assert(instance);
    161         assert(instance->bw_count);
    162161        assert(ep);
    163         const size_t bw = instance->bw_count(ep->speed, ep->transfer_type,
     162        size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type,
    164163            data_size, ep->max_packet_size);
    165 
    166         fibril_mutex_lock(&instance->guard);
    167 
    168         if (bw > instance->free_bw) {
    169                 fibril_mutex_unlock(&instance->guard);
    170                 return ENOSPC;
    171         }
     164        assert(instance);
    172165
    173166        unsigned long key[MAX_KEYS] =
    174167            {ep->address, ep->endpoint, ep->direction};
    175 
    176         const link_t *item =
     168        fibril_mutex_lock(&instance->guard);
     169
     170        link_t *item =
    177171            hash_table_find(&instance->ep_table, key);
    178172        if (item != NULL) {
    179173                fibril_mutex_unlock(&instance->guard);
    180174                return EEXISTS;
     175        }
     176
     177        if (bw > instance->free_bw) {
     178                fibril_mutex_unlock(&instance->guard);
     179                return ENOSPC;
    181180        }
    182181
     
    194193        instance->free_bw -= bw;
    195194        fibril_mutex_unlock(&instance->guard);
     195        fibril_condvar_broadcast(&instance->change);
    196196        return EOK;
    197197}
     
    211211
    212212        node_t *node = hash_table_get_instance(item, node_t, link);
    213         if (node->ep->active) {
    214                 fibril_mutex_unlock(&instance->guard);
     213        if (node->ep->active)
    215214                return EBUSY;
    216         }
    217215
    218216        instance->free_bw += node->bw;
     
    220218
    221219        fibril_mutex_unlock(&instance->guard);
     220        fibril_condvar_broadcast(&instance->change);
    222221        return EOK;
    223222}
     
    231230
    232231        fibril_mutex_lock(&instance->guard);
    233         const link_t *item = hash_table_find(&instance->ep_table, key);
     232        link_t *item = hash_table_find(&instance->ep_table, key);
    234233        if (item == NULL) {
    235234                fibril_mutex_unlock(&instance->guard);
    236235                return NULL;
    237236        }
    238         const node_t *node = hash_table_get_instance(item, node_t, link);
     237        node_t *node = hash_table_get_instance(item, node_t, link);
    239238        if (bw)
    240239                *bw = node->bw;
     
    256255{
    257256        assert(instance);
    258         if (!usb_target_is_valid(target)) {
     257        if (target.endpoint > 15 || target.endpoint < 0
     258            || target.address >= USB11_ADDRESS_MAX || target.address < 0) {
    259259                usb_log_error("Invalid data when checking for toggle reset.\n");
    260260                return;
    261261        }
    262262
    263         assert(data);
    264263        switch (data[1])
    265264        {
    266         case 0x01: /* Clear Feature -- resets only cleared ep */
    267                 /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */
     265        case 0x01: /*clear feature*/
     266                /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
    268267                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    269268                        /* endpoint number is < 16, thus first byte is enough */
     
    277276        break;
    278277
    279         case 0x9: /* Set Configuration */
    280         case 0x11: /* Set Interface */
    281                 /* Recipient must be device */
     278        case 0x9: /* set configuration */
     279        case 0x11: /* set interface */
     280                /* target must be device */
    282281                if ((data[0] & 0xf) == 0) {
    283282                        usb_target_t reset_target =
  • uspace/srv/hid/console/console.c

    rf1d6866 r85ff862  
    6060#define CONSOLE_MARGIN  12
    6161
    62 #define STATE_START   100
     62#define STATE_START   110
    6363#define STATE_TOP     8
    6464#define STATE_SPACE   4
     
    368368static console_t *cons_find_icon(sysarg_t x, sysarg_t y)
    369369{
    370         sysarg_t status_start =
    371             STATE_START + (xres - 800) / 2 + CONSOLE_MARGIN;
     370        sysarg_t status_start = STATE_START + (xres - 800) / 2;
    372371       
    373372        if ((y < STATE_TOP) || (y >= STATE_TOP + STATE_HEIGHT))
     
    380379                return NULL;
    381380       
    382         if (((x - status_start) % (STATE_WIDTH + STATE_SPACE)) >= STATE_WIDTH)
     381        if (((x - status_start) % (STATE_WIDTH + STATE_SPACE)) < STATE_SPACE)
    383382                return NULL;
    384383       
     
    895894        fb_vp_get_caps(fb_sess, console_vp, &ccaps);
    896895       
    897         mouse.x = xres / 2;
    898         mouse.y = yres / 2;
    899896        mouse.pressed = false;
    900897       
  • uspace/srv/hid/fb/port/kfb.c

    rf1d6866 r85ff862  
    422422{
    423423        if (kfb.backbuf == NULL) {
    424                 kfb.backbuf =
    425                     malloc(kfb.width * kfb.height * kfb.pixel_bytes);
     424                kfb.backbuf = malloc(kfb.size);
    426425                if (kfb.backbuf == NULL)
    427426                        return ENOMEM;
    428427        }
    429428       
    430         for (sysarg_t y = 0; y < kfb.height; y++)
    431                 memcpy(kfb.backbuf + y * kfb.width * kfb.pixel_bytes,
    432                     kfb.addr + FB_POS(0, y), kfb.width * kfb.pixel_bytes);
    433        
     429        memcpy(kfb.backbuf, kfb.addr, kfb.size);
    434430        return EOK;
    435431}
     
    440436                return ENOENT;
    441437       
    442         for (sysarg_t y = 0; y < kfb.height; y++)
    443                 memcpy(kfb.addr + FB_POS(0, y),
    444                     kfb.backbuf + y * kfb.width * kfb.pixel_bytes,
    445                     kfb.width * kfb.pixel_bytes);
    446        
     438        memcpy(kfb.addr, kfb.backbuf, kfb.size);
    447439        return EOK;
    448440}
Note: See TracChangeset for help on using the changeset viewer.