Changeset 72af8da in mainline for uspace/drv/uhci-hcd/transfer_list.c
- Timestamp:
- 2011-03-16T18:50:17Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 42a3a57
- Parents:
- 3e7b7cd (diff), fcf07e6 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/uhci-hcd/transfer_list.c
r3e7b7cd r72af8da 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 32 * @brief UHCI driver transfer list implementation 33 33 */ 34 34 #include <errno.h> 35 36 35 #include <usb/debug.h> 37 36 38 37 #include "transfer_list.h" 39 38 39 static void transfer_list_remove_batch( 40 transfer_list_t *instance, batch_t *batch); 41 /*----------------------------------------------------------------------------*/ 42 /** Initialize transfer list structures. 43 * 44 * @param[in] instance Memory place to use. 45 * @param[in] name Name of the new list. 46 * @return Error code 47 * 48 * Allocates memory for internal qh_t structure. 49 */ 40 50 int transfer_list_init(transfer_list_t *instance, const char *name) 41 51 { 42 52 assert(instance); 43 instance->next = NULL;44 53 instance->name = name; 45 instance->queue_head = queue_head_get();54 instance->queue_head = malloc32(sizeof(qh_t)); 46 55 if (!instance->queue_head) { 47 56 usb_log_error("Failed to allocate queue head.\n"); 48 57 return ENOMEM; 49 58 } 50 instance->queue_head_pa = (uintptr_t)addr_to_phys(instance->queue_head);51 52 q ueue_head_init(instance->queue_head);59 instance->queue_head_pa = addr_to_phys(instance->queue_head); 60 61 qh_init(instance->queue_head); 53 62 list_initialize(&instance->batch_list); 54 63 fibril_mutex_initialize(&instance->guard); … … 56 65 } 57 66 /*----------------------------------------------------------------------------*/ 67 /** Set the next list in transfer list chain. 68 * 69 * @param[in] instance List to lead. 70 * @param[in] next List to append. 71 * @return Error code 72 * 73 * Does not check whether this replaces an existing list . 74 */ 58 75 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next) 59 76 { … … 62 79 if (!instance->queue_head) 63 80 return; 64 queue_head_append_qh(instance->queue_head, next->queue_head_pa); 65 instance->queue_head->element = instance->queue_head->next_queue; 66 } 67 /*----------------------------------------------------------------------------*/ 81 /* Set both next and element to point to the same QH */ 82 qh_set_next_qh(instance->queue_head, next->queue_head_pa); 83 qh_set_element_qh(instance->queue_head, next->queue_head_pa); 84 } 85 /*----------------------------------------------------------------------------*/ 86 /** Submit transfer batch to the list and queue. 87 * 88 * @param[in] instance List to use. 89 * @param[in] batch Transfer batch to submit. 90 * @return Error code 91 * 92 * The batch is added to the end of the list and queue. 93 */ 68 94 void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch) 69 95 { 70 96 assert(instance); 71 97 assert(batch); 72 usb_log_debug2(" Adding batch(%p) to queue %s.\n", batch, instance->name);73 74 uint32_t pa = (uintptr_t)addr_to_phys(batch->qh);98 usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch); 99 100 const uint32_t pa = addr_to_phys(batch->qh); 75 101 assert((pa & LINK_POINTER_ADDRESS_MASK) == pa); 76 pa |= LINK_POINTER_QUEUE_HEAD_FLAG; 77 78 batch->qh->next_queue = instance->queue_head->next_queue; 102 103 /* New batch will be added to the end of the current list 104 * so set the link accordingly */ 105 qh_set_next_qh(batch->qh, instance->queue_head->next); 79 106 80 107 fibril_mutex_lock(&instance->guard); 81 108 82 if (instance->queue_head->element == instance->queue_head->next_queue) { 83 /* there is nothing scheduled */ 84 list_append(&batch->link, &instance->batch_list); 85 instance->queue_head->element = pa; 86 usb_log_debug("Batch(%p) added to queue %s first.\n", 87 batch, instance->name); 88 fibril_mutex_unlock(&instance->guard); 89 return; 90 } 91 /* now we can be sure that there is someting scheduled */ 92 assert(!list_empty(&instance->batch_list)); 109 /* Add to the hardware queue. */ 110 if (list_empty(&instance->batch_list)) { 111 /* There is nothing scheduled */ 112 qh_t *qh = instance->queue_head; 113 assert(qh->element == qh->next); 114 qh_set_element_qh(qh, pa); 115 } else { 116 /* There is something scheduled */ 117 batch_t *last = list_get_instance( 118 instance->batch_list.prev, batch_t, link); 119 qh_set_next_qh(last->qh, pa); 120 } 121 /* Add to the driver list */ 122 list_append(&batch->link, &instance->batch_list); 123 93 124 batch_t *first = list_get_instance( 94 instance->batch_list.next, batch_t, link); 95 batch_t *last = list_get_instance( 96 instance->batch_list.prev, batch_t, link); 97 queue_head_append_qh(last->qh, pa); 98 list_append(&batch->link, &instance->batch_list); 99 usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n", 100 batch, instance->name, first ); 125 instance->batch_list.next, batch_t, link); 126 usb_log_debug("Batch(%p) added to queue %s, first is %p.\n", 127 batch, instance->name, first); 101 128 fibril_mutex_unlock(&instance->guard); 102 129 } 103 130 /*----------------------------------------------------------------------------*/ 104 static void transfer_list_remove_batch( 105 transfer_list_t *instance, batch_t *batch) 131 /** Remove a transfer batch from the list and queue. 132 * 133 * @param[in] instance List to use. 134 * @param[in] batch Transfer batch to remove. 135 * @return Error code 136 * 137 * Does not lock the transfer list, caller is responsible for that. 138 */ 139 void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch) 106 140 { 107 141 assert(instance); … … 109 143 assert(instance->queue_head); 110 144 assert(batch->qh); 111 usb_log_debug2("Removing batch(%p) from queue %s.\n", batch, instance->name); 112 113 /* I'm the first one here */ 145 usb_log_debug2( 146 "Queue %s: removing batch(%p).\n", instance->name, batch); 147 148 const char * pos = NULL; 149 /* Remove from the hardware queue */ 114 150 if (batch->link.prev == &instance->batch_list) { 115 usb_log_debug("Batch(%p) removed (FIRST) from queue %s, next element %x.\n",116 batch, instance->name, batch->qh->next_queue);117 instance->queue_head->element = batch->qh->next_queue;151 /* I'm the first one here */ 152 qh_set_element_qh(instance->queue_head, batch->qh->next); 153 pos = "FIRST"; 118 154 } else { 119 usb_log_debug("Batch(%p) removed (NOT FIRST) from queue, next element %x.\n", 120 batch, instance->name, batch->qh->next_queue); 121 batch_t *prev = list_get_instance(batch->link.prev, batch_t, link); 122 prev->qh->next_queue = batch->qh->next_queue; 123 } 155 batch_t *prev = 156 list_get_instance(batch->link.prev, batch_t, link); 157 qh_set_next_qh(prev->qh, batch->qh->next); 158 pos = "NOT FIRST"; 159 } 160 /* Remove from the driver list */ 124 161 list_remove(&batch->link); 125 } 126 /*----------------------------------------------------------------------------*/ 162 usb_log_debug("Batch(%p) removed (%s) from %s, next element %x.\n", 163 batch, pos, instance->name, batch->qh->next); 164 } 165 /*----------------------------------------------------------------------------*/ 166 /** Check list for finished batches. 167 * 168 * @param[in] instance List to use. 169 * @return Error code 170 * 171 * Creates a local list of finished batches and calls next_step on each and 172 * every one. This is safer because next_step may theoretically access 173 * this transfer list leading to the deadlock if its done inline. 174 */ 127 175 void transfer_list_remove_finished(transfer_list_t *instance) 128 176 { … … 138 186 139 187 if (batch_is_complete(batch)) { 188 /* Save for post-processing */ 140 189 transfer_list_remove_batch(instance, batch); 141 190 list_append(current, &done);
Note:
See TracChangeset
for help on using the changeset viewer.