Changeset 4f66cc7b in mainline for uspace/drv/uhci-hcd/transfer_list.c
- Timestamp:
- 2011-03-17T12:45:23Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4fec9ee, 6e3b9a58
- Parents:
- 45dd8bf (diff), 039c66c (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
r45dd8bf r4f66cc7b 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 … … 41 40 transfer_list_t *instance, batch_t *batch); 42 41 /*----------------------------------------------------------------------------*/ 43 /** Initialize stransfer list structures.42 /** Initialize transfer list structures. 44 43 * 45 44 * @param[in] instance Memory place to use. 46 * @param[in] name Name of t e new list.47 * @return Error code 48 * 49 * Allocates memory for interna t queue_head_t structure.45 * @param[in] name Name of the new list. 46 * @return Error code 47 * 48 * Allocates memory for internal qh_t structure. 50 49 */ 51 50 int transfer_list_init(transfer_list_t *instance, const char *name) 52 51 { 53 52 assert(instance); 54 instance->next = NULL;55 53 instance->name = name; 56 instance->queue_head = malloc32(sizeof(q ueue_head_t));54 instance->queue_head = malloc32(sizeof(qh_t)); 57 55 if (!instance->queue_head) { 58 56 usb_log_error("Failed to allocate queue head.\n"); … … 61 59 instance->queue_head_pa = addr_to_phys(instance->queue_head); 62 60 63 q ueue_head_init(instance->queue_head);61 qh_init(instance->queue_head); 64 62 list_initialize(&instance->batch_list); 65 63 fibril_mutex_initialize(&instance->guard); … … 67 65 } 68 66 /*----------------------------------------------------------------------------*/ 69 /** Set the next list in chain.67 /** Set the next list in transfer list chain. 70 68 * 71 69 * @param[in] instance List to lead. 72 70 * @param[in] next List to append. 73 71 * @return Error code 72 * 73 * Does not check whether this replaces an existing list . 74 74 */ 75 75 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next) … … 79 79 if (!instance->queue_head) 80 80 return; 81 queue_head_append_qh(instance->queue_head, next->queue_head_pa); 82 instance->queue_head->element = instance->queue_head->next_queue; 83 } 84 /*----------------------------------------------------------------------------*/ 85 /** Submits a new transfer batch to list and queue. 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. 86 87 * 87 88 * @param[in] instance List to use. 88 89 * @param[in] batch Transfer batch to submit. 89 90 * @return Error code 91 * 92 * The batch is added to the end of the list and queue. 90 93 */ 91 94 void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch) … … 93 96 assert(instance); 94 97 assert(batch); 95 usb_log_debug2( 96 "Adding batch(%p) to queue %s.\n", batch, instance->name); 97 98 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); 99 101 assert((pa & LINK_POINTER_ADDRESS_MASK) == pa); 100 pa |= LINK_POINTER_QUEUE_HEAD_FLAG; 101 102 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); 103 106 104 107 fibril_mutex_lock(&instance->guard); 105 108 106 if (instance->queue_head->element == instance->queue_head->next_queue) { 107 /* there is nothing scheduled */ 108 list_append(&batch->link, &instance->batch_list); 109 instance->queue_head->element = pa; 110 usb_log_debug("Batch(%p) added to queue %s first.\n", 111 batch, instance->name); 112 fibril_mutex_unlock(&instance->guard); 113 return; 114 } 115 /* now we can be sure that there is someting scheduled */ 116 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 117 124 batch_t *first = list_get_instance( 118 instance->batch_list.next, batch_t, link); 119 batch_t *last = list_get_instance( 120 instance->batch_list.prev, batch_t, link); 121 queue_head_append_qh(last->qh, pa); 122 list_append(&batch->link, &instance->batch_list); 123 124 usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n", 125 instance->batch_list.next, batch_t, link); 126 usb_log_debug("Batch(%p) added to queue %s, first is %p.\n", 125 127 batch, instance->name, first); 126 128 fibril_mutex_unlock(&instance->guard); 127 129 } 128 130 /*----------------------------------------------------------------------------*/ 129 /** Remove s a transfer batch fromlist and queue.131 /** Remove a transfer batch from the list and queue. 130 132 * 131 133 * @param[in] instance List to use. 132 134 * @param[in] batch Transfer batch to remove. 133 135 * @return Error code 136 * 137 * Does not lock the transfer list, caller is responsible for that. 134 138 */ 135 139 void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch) … … 140 144 assert(batch->qh); 141 145 usb_log_debug2( 142 "Removing batch(%p) from queue %s.\n", batch, instance->name); 143 146 "Queue %s: removing batch(%p).\n", instance->name, batch); 147 148 const char * pos = NULL; 149 /* Remove from the hardware queue */ 144 150 if (batch->link.prev == &instance->batch_list) { 145 151 /* I'm the first one here */ 146 usb_log_debug( 147 "Batch(%p) removed (FIRST) from %s, next element %x.\n", 148 batch, instance->name, batch->qh->next_queue); 149 instance->queue_head->element = batch->qh->next_queue; 152 qh_set_element_qh(instance->queue_head, batch->qh->next); 153 pos = "FIRST"; 150 154 } else { 151 usb_log_debug(152 "Batch(%p) removed (FIRST:NO) from %s, next element %x.\n",153 batch, instance->name, batch->qh->next_queue);154 155 batch_t *prev = 155 156 list_get_instance(batch->link.prev, batch_t, link); 156 prev->qh->next_queue = batch->qh->next_queue; 157 } 157 qh_set_next_qh(prev->qh, batch->qh->next); 158 pos = "NOT FIRST"; 159 } 160 /* Remove from the driver list */ 158 161 list_remove(&batch->link); 159 } 160 /*----------------------------------------------------------------------------*/ 161 /** Checks list for finished transfers. 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. 162 167 * 163 168 * @param[in] instance List to use. 164 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. 165 174 */ 166 175 void transfer_list_remove_finished(transfer_list_t *instance) … … 177 186 178 187 if (batch_is_complete(batch)) { 188 /* Save for post-processing */ 179 189 transfer_list_remove_batch(instance, batch); 180 190 list_append(current, &done);
Note:
See TracChangeset
for help on using the changeset viewer.