00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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
00099 if (list_empty(&instance->endpoint_list)) {
00100
00101 last_ed = instance->list_head;
00102 } else {
00103
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
00110 hcd_ep->ed->next = last_ed->next;
00111
00112 write_barrier();
00113
00114
00115 ed_append_ed(last_ed, hcd_ep->ed);
00116
00117 write_barrier();
00118
00119
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
00155 if (instance->endpoint_list.next == &hcd_ep->link) {
00156
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
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
00174 list_remove(&hcd_ep->link);
00175 fibril_mutex_unlock(&instance->guard);
00176 }