endpoint_list.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011 Jan Vesely
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00034 #include <errno.h>
00035 #include <usb/debug.h>
00036 #include <arch/barrier.h>
00037 
00038 #include "endpoint_list.h"
00039 
00048 int endpoint_list_init(endpoint_list_t *instance, const char *name)
00049 {
00050         assert(instance);
00051         instance->name = name;
00052         instance->list_head = malloc32(sizeof(ed_t));
00053         if (!instance->list_head) {
00054                 usb_log_error("Failed to allocate list head.\n");
00055                 return ENOMEM;
00056         }
00057         instance->list_head_pa = addr_to_phys(instance->list_head);
00058         usb_log_debug2("Transfer list %s setup with ED: %p(0x%0" PRIx32 ")).\n",
00059             name, instance->list_head, instance->list_head_pa);
00060 
00061         ed_init(instance->list_head, NULL);
00062         list_initialize(&instance->endpoint_list);
00063         fibril_mutex_initialize(&instance->guard);
00064         return EOK;
00065 }
00066 /*----------------------------------------------------------------------------*/
00074 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next)
00075 {
00076         assert(instance);
00077         assert(next);
00078         ed_append_ed(instance->list_head, next->list_head);
00079 }
00080 /*----------------------------------------------------------------------------*/
00088 void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
00089 {
00090         assert(instance);
00091         assert(hcd_ep);
00092         usb_log_debug2("Queue %s: Adding endpoint(%p).\n",
00093             instance->name, hcd_ep);
00094 
00095         fibril_mutex_lock(&instance->guard);
00096 
00097         ed_t *last_ed = NULL;
00098         /* Add to the hardware queue. */
00099         if (list_empty(&instance->endpoint_list)) {
00100                 /* There are no active EDs */
00101                 last_ed = instance->list_head;
00102         } else {
00103                 /* There are active EDs, get the last one */
00104                 hcd_endpoint_t *last = list_get_instance(
00105                     instance->endpoint_list.prev, hcd_endpoint_t, link);
00106                 assert(last);
00107                 last_ed = last->ed;
00108         }
00109         /* Keep link */
00110         hcd_ep->ed->next = last_ed->next;
00111         /* Make sure ED is written to the memory */
00112         write_barrier();
00113 
00114         /* Add ed to the hw queue */
00115         ed_append_ed(last_ed, hcd_ep->ed);
00116         /* Make sure ED is updated */
00117         write_barrier();
00118 
00119         /* Add to the sw list */
00120         list_append(&hcd_ep->link, &instance->endpoint_list);
00121 
00122         hcd_endpoint_t *first = list_get_instance(
00123             instance->endpoint_list.next, hcd_endpoint_t, link);
00124         usb_log_debug("HCD EP(%p) added to list %s, first is %p(%p).\n",
00125                 hcd_ep, instance->name, first, first->ed);
00126         if (last_ed == instance->list_head) {
00127                 usb_log_debug2("%s head ED(%p-0x%0" PRIx32 "): %x:%x:%x:%x.\n",
00128                     instance->name, last_ed, instance->list_head_pa,
00129                     last_ed->status, last_ed->td_tail, last_ed->td_head,
00130                     last_ed->next);
00131         }
00132         fibril_mutex_unlock(&instance->guard);
00133 }
00134 /*----------------------------------------------------------------------------*/
00140 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
00141 {
00142         assert(instance);
00143         assert(instance->list_head);
00144         assert(hcd_ep);
00145         assert(hcd_ep->ed);
00146 
00147         fibril_mutex_lock(&instance->guard);
00148 
00149         usb_log_debug2(
00150             "Queue %s: removing endpoint(%p).\n", instance->name, hcd_ep);
00151 
00152         const char *qpos = NULL;
00153         ed_t *prev_ed;
00154         /* Remove from the hardware queue */
00155         if (instance->endpoint_list.next == &hcd_ep->link) {
00156                 /* I'm the first one here */
00157                 prev_ed = instance->list_head;
00158                 qpos = "FIRST";
00159         } else {
00160                 hcd_endpoint_t *prev =
00161                     list_get_instance(hcd_ep->link.prev, hcd_endpoint_t, link);
00162                 prev_ed = prev->ed;
00163                 qpos = "NOT FIRST";
00164         }
00165         assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed));
00166         prev_ed->next = hcd_ep->ed->next;
00167         /* Make sure ED is updated */
00168         write_barrier();
00169 
00170         usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n",
00171             hcd_ep, qpos, instance->name, hcd_ep->ed->next);
00172 
00173         /* Remove from the endpoint list */
00174         list_remove(&hcd_ep->link);
00175         fibril_mutex_unlock(&instance->guard);
00176 }

Generated on Thu Jun 2 07:45:44 2011 for HelenOS/USB by  doxygen 1.4.7