Changes in uspace/drv/ohci/hc.c [4125b7d:8790650] in mainline


Ignore:
File:
1 edited

Legend:

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

    r4125b7d r8790650  
    4343
    4444#include "hc.h"
    45 #include "hcd_endpoint.h"
    4645
    4746static int interrupt_emulator(hc_t *instance);
     
    5655        assert(hub_fun);
    5756
    58         int ret;
    59 
    6057        usb_address_t hub_address =
    6158            device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL);
    62         if (hub_address <= 0) {
    63                 usb_log_error("Failed to get OHCI root hub address.\n");
    64                 return hub_address;
    65         }
    6659        instance->rh.address = hub_address;
    6760        usb_device_keeper_bind(
    6861            &instance->manager, hub_address, hub_fun->handle);
    6962
    70         ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
    71             USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
    72         if (ret != EOK) {
    73                 usb_log_error("Failed to add OHCI rh endpoint 0.\n");
    74                 usb_device_keeper_release(&instance->manager, hub_address);
    75                 return ret;
    76         }
     63        endpoint_t *ep = malloc(sizeof(endpoint_t));
     64        assert(ep);
     65        int ret = endpoint_init(ep, hub_address, 0, USB_DIRECTION_BOTH,
     66            USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64);
     67        assert(ret == EOK);
     68        ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, 0);
     69        assert(ret == EOK);
    7770
    7871        char *match_str = NULL;
    79         /* DDF needs heap allocated string */
    8072        ret = asprintf(&match_str, "usb&class=hub");
     73//      ret = (match_str == NULL) ? ret : EOK;
    8174        if (ret < 0) {
    8275                usb_log_error(
    8376                    "Failed(%d) to create root hub match-id string.\n", ret);
    84                 usb_device_keeper_release(&instance->manager, hub_address);
    8577                return ret;
    8678        }
     
    8880        ret = ddf_fun_add_match_id(hub_fun, match_str, 100);
    8981        if (ret != EOK) {
    90                 usb_log_error("Failed add root hub match-id.\n");
     82                usb_log_error("Failed add create root hub match-id.\n");
    9183        }
    9284        return ret;
     
    109101            ret, str_error(ret));
    110102
     103        instance->ddf_instance = fun;
    111104        usb_device_keeper_init(&instance->manager);
    112105        ret = usb_endpoint_manager_init(&instance->ep_manager,
    113106            BANDWIDTH_AVAILABLE_USB11);
    114107        CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
    115             str_error(ret));
     108            ret, str_error(ret));
    116109
    117110        hc_gain_control(instance);
    118111        ret = hc_init_memory(instance);
    119         CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures: %s.\n",
    120             str_error(ret));
     112        CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures:%s.\n",
     113            ret, str_error(ret));
    121114        hc_init_hw(instance);
    122         fibril_mutex_initialize(&instance->guard);
    123 
    124         rh_init(&instance->rh, instance->registers);
     115
     116        rh_init(&instance->rh, dev, instance->registers);
    125117
    126118        if (!interrupts) {
     
    130122        }
    131123
    132         list_initialize(&instance->pending_batches);
    133 #undef CHECK_RET_RETURN
    134         return EOK;
    135 }
    136 /*----------------------------------------------------------------------------*/
    137 int hc_add_endpoint(
    138     hc_t *instance, usb_address_t address, usb_endpoint_t endpoint,
    139     usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
    140     size_t mps, size_t size, unsigned interval)
    141 {
    142         endpoint_t *ep = malloc(sizeof(endpoint_t));
    143         if (ep == NULL)
    144                 return ENOMEM;
    145         int ret =
    146             endpoint_init(ep, address, endpoint, direction, type, speed, mps);
    147         if (ret != EOK) {
    148                 free(ep);
    149                 return ret;
    150         }
    151 
    152         hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep);
    153         if (hcd_ep == NULL) {
    154                 endpoint_destroy(ep);
    155                 return ENOMEM;
    156         }
    157 
    158         ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
    159         if (ret != EOK) {
    160                 hcd_endpoint_clear(ep);
    161                 endpoint_destroy(ep);
    162                 return ret;
    163         }
    164 
    165         /* Enqueue hcd_ep */
    166         switch (ep->transfer_type) {
     124        return EOK;
     125}
     126/*----------------------------------------------------------------------------*/
     127int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
     128{
     129        assert(instance);
     130        assert(batch);
     131
     132        /* check for root hub communication */
     133        if (batch->target.address == instance->rh.address) {
     134                return rh_request(&instance->rh, batch);
     135        }
     136
     137        transfer_list_add_batch(
     138            instance->transfers[batch->transfer_type], batch);
     139
     140        switch (batch->transfer_type) {
    167141        case USB_TRANSFER_CONTROL:
    168142                instance->registers->control &= ~C_CLE;
    169                 endpoint_list_add_ep(
    170                     &instance->lists[ep->transfer_type], hcd_ep);
    171                 instance->registers->control_current = 0;
     143                instance->registers->command_status |= CS_CLF;
     144                usb_log_debug2("Set control transfer filled: %x.\n",
     145                        instance->registers->command_status);
    172146                instance->registers->control |= C_CLE;
    173147                break;
    174148        case USB_TRANSFER_BULK:
    175                 instance->registers->control &= ~C_BLE;
    176                 endpoint_list_add_ep(
    177                     &instance->lists[ep->transfer_type], hcd_ep);
    178                 instance->registers->control |= C_BLE;
    179                 break;
    180         case USB_TRANSFER_ISOCHRONOUS:
    181         case USB_TRANSFER_INTERRUPT:
    182                 instance->registers->control &= (~C_PLE & ~C_IE);
    183                 endpoint_list_add_ep(
    184                     &instance->lists[ep->transfer_type], hcd_ep);
    185                 instance->registers->control |= C_PLE | C_IE;
     149                instance->registers->command_status |= CS_BLF;
     150                usb_log_debug2("Set bulk transfer filled: %x.\n",
     151                        instance->registers->command_status);
    186152                break;
    187153        default:
    188154                break;
    189155        }
    190 
    191         return EOK;
    192 }
    193 /*----------------------------------------------------------------------------*/
    194 int hc_remove_endpoint(hc_t *instance, usb_address_t address,
    195     usb_endpoint_t endpoint, usb_direction_t direction)
    196 {
    197         assert(instance);
    198         fibril_mutex_lock(&instance->guard);
    199         endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
    200             address, endpoint, direction, NULL);
    201         if (ep == NULL) {
    202                 usb_log_error("Endpoint unregister failed: No such EP.\n");
    203                 fibril_mutex_unlock(&instance->guard);
    204                 return ENOENT;
    205         }
    206 
    207         hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
    208         if (hcd_ep) {
    209                 /* Dequeue hcd_ep */
    210                 switch (ep->transfer_type) {
    211                 case USB_TRANSFER_CONTROL:
    212                         instance->registers->control &= ~C_CLE;
    213                         endpoint_list_remove_ep(
    214                             &instance->lists[ep->transfer_type], hcd_ep);
    215                         instance->registers->control_current = 0;
    216                         instance->registers->control |= C_CLE;
    217                         break;
    218                 case USB_TRANSFER_BULK:
    219                         instance->registers->control &= ~C_BLE;
    220                         endpoint_list_remove_ep(
    221                             &instance->lists[ep->transfer_type], hcd_ep);
    222                         instance->registers->control |= C_BLE;
    223                         break;
    224                 case USB_TRANSFER_ISOCHRONOUS:
    225                 case USB_TRANSFER_INTERRUPT:
    226                         instance->registers->control &= (~C_PLE & ~C_IE);
    227                         endpoint_list_remove_ep(
    228                             &instance->lists[ep->transfer_type], hcd_ep);
    229                         instance->registers->control |= C_PLE | C_IE;
    230                         break;
    231                 default:
    232                         break;
    233                 }
    234                 hcd_endpoint_clear(ep);
    235         } else {
    236                 usb_log_warning("Endpoint without hcd equivalent structure.\n");
    237         }
    238         int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager,
    239             address, endpoint, direction);
    240         fibril_mutex_unlock(&instance->guard);
    241         return ret;
    242 }
    243 /*----------------------------------------------------------------------------*/
    244 endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
    245     usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw)
    246 {
    247         assert(instance);
    248         fibril_mutex_lock(&instance->guard);
    249         endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
    250             address, endpoint, direction, bw);
    251         fibril_mutex_unlock(&instance->guard);
    252         return ep;
    253 }
    254 /*----------------------------------------------------------------------------*/
    255 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
    256 {
    257         assert(instance);
    258         assert(batch);
    259         assert(batch->ep);
    260 
    261         /* check for root hub communication */
    262         if (batch->ep->address == instance->rh.address) {
    263                 return rh_request(&instance->rh, batch);
    264         }
    265 
    266         fibril_mutex_lock(&instance->guard);
    267         list_append(&batch->link, &instance->pending_batches);
    268         batch_commit(batch);
    269         switch (batch->ep->transfer_type) {
    270         case USB_TRANSFER_CONTROL:
    271                 instance->registers->command_status |= CS_CLF;
    272                 break;
    273         case USB_TRANSFER_BULK:
    274                 instance->registers->command_status |= CS_BLF;
    275                 break;
    276         default:
    277                 break;
    278         }
    279 
    280         fibril_mutex_unlock(&instance->guard);
    281156        return EOK;
    282157}
     
    290165                rh_interrupt(&instance->rh);
    291166
    292         usb_log_debug("OHCI interrupt: %x.\n", status);
    293 
    294         if (status & IS_WDH) {
    295                 fibril_mutex_lock(&instance->guard);
    296                 usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
    297                     instance->registers->hcca,
    298                     (void *) addr_to_phys(instance->hcca));
    299                 usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
    300                     instance->registers->periodic_current);
    301 
    302                 link_t *current = instance->pending_batches.next;
    303                 while (current != &instance->pending_batches) {
    304                         link_t *next = current->next;
    305                         usb_transfer_batch_t *batch =
    306                             usb_transfer_batch_from_link(current);
    307 
    308                         if (batch_is_complete(batch)) {
    309                                 list_remove(current);
    310                                 usb_transfer_batch_finish(batch);
    311                         }
    312                         current = next;
    313                 }
    314                 fibril_mutex_unlock(&instance->guard);
     167        usb_log_info("OHCI interrupt: %x.\n", status);
     168
     169
     170        LIST_INITIALIZE(done);
     171        transfer_list_remove_finished(&instance->transfers_interrupt, &done);
     172        transfer_list_remove_finished(&instance->transfers_isochronous, &done);
     173        transfer_list_remove_finished(&instance->transfers_control, &done);
     174        transfer_list_remove_finished(&instance->transfers_bulk, &done);
     175
     176        while (!list_empty(&done)) {
     177                link_t *item = done.next;
     178                list_remove(item);
     179                usb_transfer_batch_t *batch =
     180                    list_get_instance(item, usb_transfer_batch_t, link);
     181                usb_transfer_batch_finish(batch);
    315182        }
    316183}
     
    324191                instance->registers->interrupt_status = status;
    325192                hc_interrupt(instance, status);
    326                 async_usleep(50000);
     193                async_usleep(1000);
    327194        }
    328195        return EOK;
     
    400267            instance->registers->control);
    401268
    402         /* Use HCCA */
    403         instance->registers->hcca = addr_to_phys(instance->hcca);
    404 
    405         /* Use queues */
    406         instance->registers->bulk_head =
    407             instance->lists[USB_TRANSFER_BULK].list_head_pa;
    408         usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
    409             instance->lists[USB_TRANSFER_BULK].list_head,
    410             instance->lists[USB_TRANSFER_BULK].list_head_pa);
    411 
    412         instance->registers->control_head =
    413             instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
    414         usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
    415             instance->lists[USB_TRANSFER_CONTROL].list_head,
    416             instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
    417 
    418269        /* Enable queues */
    419270        instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
     
    445296        assert(instance);
    446297
    447 #define SETUP_ENDPOINT_LIST(type) \
     298#define SETUP_TRANSFER_LIST(type, name) \
    448299do { \
    449         const char *name = usb_str_transfer_type(type); \
    450         int ret = endpoint_list_init(&instance->lists[type], name); \
     300        int ret = transfer_list_init(&instance->type, name); \
    451301        if (ret != EOK) { \
    452                 usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
     302                usb_log_error("Failed(%d) to setup %s transfer list.\n", \
    453303                    ret, name); \
    454                 endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \
    455                 endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
    456                 endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \
    457                 endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \
     304                transfer_list_fini(&instance->transfers_isochronous); \
     305                transfer_list_fini(&instance->transfers_interrupt); \
     306                transfer_list_fini(&instance->transfers_control); \
     307                transfer_list_fini(&instance->transfers_bulk); \
    458308        } \
    459309} while (0)
    460310
    461         SETUP_ENDPOINT_LIST(USB_TRANSFER_ISOCHRONOUS);
    462         SETUP_ENDPOINT_LIST(USB_TRANSFER_INTERRUPT);
    463         SETUP_ENDPOINT_LIST(USB_TRANSFER_CONTROL);
    464         SETUP_ENDPOINT_LIST(USB_TRANSFER_BULK);
    465 #undef SETUP_ENDPOINT_LIST
    466         endpoint_list_set_next(&instance->lists[USB_TRANSFER_INTERRUPT],
    467             &instance->lists[USB_TRANSFER_ISOCHRONOUS]);
    468 
    469         return EOK;
     311        SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS");
     312        SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT");
     313        SETUP_TRANSFER_LIST(transfers_control, "CONTROL");
     314        SETUP_TRANSFER_LIST(transfers_bulk, "BULK");
     315
     316        transfer_list_set_next(&instance->transfers_interrupt,
     317            &instance->transfers_isochronous);
     318
     319        /* Assign pointers to be used during scheduling */
     320        instance->transfers[USB_TRANSFER_INTERRUPT] =
     321          &instance->transfers_interrupt;
     322        instance->transfers[USB_TRANSFER_ISOCHRONOUS] =
     323          &instance->transfers_interrupt;
     324        instance->transfers[USB_TRANSFER_CONTROL] =
     325          &instance->transfers_control;
     326        instance->transfers[USB_TRANSFER_BULK] =
     327          &instance->transfers_bulk;
     328
     329        return EOK;
     330#undef CHECK_RET_CLEAR_RETURN
    470331}
    471332/*----------------------------------------------------------------------------*/
     
    481342                return ENOMEM;
    482343        bzero(instance->hcca, sizeof(hcca_t));
    483         usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
     344        instance->registers->hcca = addr_to_phys(instance->hcca);
     345        usb_log_debug2("OHCI HCCA initialized at %p(%p).\n",
     346            instance->hcca, instance->registers->hcca);
     347
     348        /* Use queues */
     349        instance->registers->bulk_head = instance->transfers_bulk.list_head_pa;
     350        usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
     351            instance->transfers_bulk.list_head,
     352            instance->transfers_bulk.list_head_pa);
     353
     354        instance->registers->control_head =
     355            instance->transfers_control.list_head_pa;
     356        usb_log_debug2("Control HEAD set to: %p(%p).\n",
     357            instance->transfers_control.list_head,
     358            instance->transfers_control.list_head_pa);
    484359
    485360        unsigned i = 0;
    486361        for (; i < 32; ++i) {
    487362                instance->hcca->int_ep[i] =
    488                     instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
    489         }
    490         usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
    491             instance->lists[USB_TRANSFER_INTERRUPT].list_head,
    492             instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
     363                    instance->transfers_interrupt.list_head_pa;
     364        }
     365        usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
     366            instance->transfers_interrupt.list_head,
     367            instance->transfers_interrupt.list_head_pa);
    493368
    494369        return EOK;
Note: See TracChangeset for help on using the changeset viewer.