Changeset 4e38d69 in mainline for uspace/drv/uhci-hcd/uhci.c
- Timestamp:
- 2011-02-11T15:05:40Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5842493
- Parents:
- 1e64b250 (diff), 03197ffc (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/uhci.c
r1e64b250 r4e38d69 33 33 */ 34 34 #include <errno.h> 35 #include <adt/list.h> 35 36 36 37 #include <usb/debug.h> … … 42 43 static int uhci_clean_finished(void *arg); 43 44 static int uhci_debug_checker(void *arg); 45 static bool allowed_usb_packet( 46 bool low_speed, usb_transfer_type_t, size_t size); 44 47 45 48 int uhci_init(uhci_t *instance, void *regs, size_t reg_size) … … 84 87 85 88 const uintptr_t pa = (uintptr_t)addr_to_phys(instance->frame_list); 86 87 89 pio_write_32(&instance->registers->flbaseadd, (uint32_t)pa); 90 91 list_initialize(&instance->tracker_list); 92 fibril_mutex_initialize(&instance->tracker_list_mutex); 88 93 89 94 instance->cleaner = fibril_create(uhci_clean_finished, instance); … … 93 98 fibril_add_ready(instance->debug_checker); 94 99 95 /* Start the hc with large(64 b) packet FSBR */100 /* Start the hc with large(64B) packet FSBR */ 96 101 pio_write_16(&instance->registers->usbcmd, 97 102 UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET); … … 147 152 } 148 153 /*----------------------------------------------------------------------------*/ 149 int uhci_transfer( 150 uhci_t *instance, 151 device_t *dev, 152 usb_target_t target, 153 usb_transfer_type_t transfer_type, 154 bool toggle, 155 usb_packet_id pid, 156 bool low_speed, 157 void *buffer, size_t size, 158 usbhc_iface_transfer_out_callback_t callback_out, 159 usbhc_iface_transfer_in_callback_t callback_in, 160 void *arg) 161 { 162 // TODO: Add support for isochronous transfers 163 if (transfer_type == USB_TRANSFER_ISOCHRONOUS) { 164 usb_log_warning("ISO transfer not supported.\n"); 154 int uhci_schedule(uhci_t *instance, tracker_t *tracker) 155 { 156 assert(instance); 157 assert(tracker); 158 const int low_speed = (tracker->speed == LOW_SPEED); 159 if (!allowed_usb_packet( 160 low_speed, tracker->transfer_type, tracker->packet_size)) { 161 usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n", 162 low_speed ? "LOW" : "FULL" , tracker->transfer_type, 163 tracker->packet_size); 165 164 return ENOTSUP; 166 165 } 167 168 if (transfer_type == USB_TRANSFER_INTERRUPT 169 && size >= 64) { 170 usb_log_warning("Interrupt transfer too big %zu.\n", size); 171 return ENOTSUP; 172 } 173 174 if (size >= 1024) { 175 usb_log_warning("Transfer too big.\n"); 176 return ENOTSUP; 177 } 178 transfer_list_t *list = instance->transfers[low_speed][transfer_type]; 179 if (!list) { 180 usb_log_warning("UNSUPPORTED transfer %d-%d.\n", low_speed, transfer_type); 181 return ENOTSUP; 182 } 183 184 transfer_descriptor_t *td = NULL; 185 callback_t *job = NULL; 186 int ret = EOK; 187 assert(dev); 188 189 #define CHECK_RET_TRANS_FREE_JOB_TD(message) \ 190 if (ret != EOK) { \ 191 usb_log_error(message); \ 192 if (job) { \ 193 callback_dispose(job); \ 194 } \ 195 if (td) { free32(td); } \ 196 return ret; \ 197 } else (void) 0 198 199 job = callback_get(dev, buffer, size, callback_in, callback_out, arg); 200 ret = job ? EOK : ENOMEM; 201 CHECK_RET_TRANS_FREE_JOB_TD("Failed to allocate callback structure.\n"); 202 203 td = transfer_descriptor_get(3, size, false, target, pid, job->new_buffer); 204 ret = td ? EOK : ENOMEM; 205 CHECK_RET_TRANS_FREE_JOB_TD("Failed to setup transfer descriptor.\n"); 206 207 td->callback = job; 208 209 210 usb_log_debug("Appending a new transfer to queue %s.\n", list->name); 211 212 ret = transfer_list_append(list, td); 213 CHECK_RET_TRANS_FREE_JOB_TD("Failed to append transfer descriptor.\n"); 166 /* TODO: check available bandwith here */ 167 168 usb_log_debug2("Scheduler(%d) acquiring tracker list mutex.\n", 169 fibril_get_id()); 170 fibril_mutex_lock(&instance->tracker_list_mutex); 171 usb_log_debug2("Scheduler(%d) acquired tracker list mutex.\n", 172 fibril_get_id()); 173 174 transfer_list_t *list = 175 instance->transfers[low_speed][tracker->transfer_type]; 176 assert(list); 177 transfer_list_add_tracker(list, tracker); 178 list_append(&tracker->link, &instance->tracker_list); 179 180 usb_log_debug2("Scheduler(%d) releasing tracker list mutex.\n", 181 fibril_get_id()); 182 fibril_mutex_unlock(&instance->tracker_list_mutex); 183 usb_log_debug2("Scheduler(%d) released tracker list mutex.\n", 184 fibril_get_id()); 214 185 215 186 return EOK; 216 187 } 217 /*--------------------------------------------------------------------------- */188 /*----------------------------------------------------------------------------*/ 218 189 int uhci_clean_finished(void* arg) 219 190 { … … 223 194 224 195 while(1) { 225 usb_log_debug("Running cleaning fibril on: %p.\n", instance); 226 /* iterate all transfer queues */ 227 transfer_list_t *current_list = &instance->transfers_interrupt; 228 while (current_list) { 229 /* Remove inactive transfers from the top of the queue 230 * TODO: should I reach queue head or is this enough? */ 231 volatile transfer_descriptor_t * it = 232 current_list->first; 233 usb_log_debug("Running cleaning fibril on queue: %s (%s).\n", 234 current_list->name, it ? "SOMETHING" : "EMPTY"); 235 236 if (it) { 237 usb_log_debug("First in queue: %p (%x) PA:%x.\n", 238 it, it->status, addr_to_phys((void*)it) ); 239 usb_log_debug("First to send: %x\n", 240 (current_list->queue_head->element) ); 196 LIST_INITIALIZE(done_trackers); 197 /* tracker iteration */ 198 199 usb_log_debug2("Cleaner(%d) acquiring tracker list mutex.\n", 200 fibril_get_id()); 201 fibril_mutex_lock(&instance->tracker_list_mutex); 202 usb_log_debug2("Cleaner(%d) acquired tracker list mutex.\n", 203 fibril_get_id()); 204 205 link_t *current = instance->tracker_list.next; 206 while (current != &instance->tracker_list) 207 { 208 209 link_t *next = current->next; 210 tracker_t *tracker = list_get_instance(current, tracker_t, link); 211 212 assert(current == &tracker->link); 213 assert(tracker); 214 assert(tracker->next_step); 215 assert(tracker->td); 216 217 if (!transfer_descriptor_is_active(tracker->td)) { 218 usb_log_info("Found inactive tracker with status: %x:%x.\n", 219 tracker->td->status, tracker->td->device); 220 list_remove(current); 221 list_append(current, &done_trackers); 241 222 } 242 243 while (current_list->first && 244 !(current_list->first->status & TD_STATUS_ERROR_ACTIVE)) { 245 transfer_descriptor_t *transfer = current_list->first; 246 usb_log_info("Inactive transfer calling callback with status %x.\n", 247 transfer->status); 248 current_list->first = transfer->next_va; 249 transfer_descriptor_dispose(transfer); 250 } 251 if (!current_list->first) 252 current_list->last = current_list->first; 253 254 current_list = current_list->next; 223 current = next; 224 } 225 226 usb_log_debug2("Cleaner(%d) releasing tracker list mutex.\n", 227 fibril_get_id()); 228 fibril_mutex_unlock(&instance->tracker_list_mutex); 229 usb_log_debug2("Cleaner(%d) released tracker list mutex.\n", 230 fibril_get_id()); 231 232 while (!list_empty(&done_trackers)) { 233 tracker_t *tracker = list_get_instance( 234 done_trackers.next, tracker_t, link); 235 list_remove(&tracker->link); 236 tracker->next_step(tracker); 255 237 } 256 238 async_usleep(UHCI_CLEANER_TIMEOUT); … … 311 293 return 0; 312 294 } 295 /*----------------------------------------------------------------------------*/ 296 bool allowed_usb_packet( 297 bool low_speed, usb_transfer_type_t transfer, size_t size) 298 { 299 /* see USB specification chapter 5.5-5.8 for magic numbers used here */ 300 switch(transfer) { 301 case USB_TRANSFER_ISOCHRONOUS: 302 return (!low_speed && size < 1024); 303 case USB_TRANSFER_INTERRUPT: 304 return size <= (low_speed ? 8 : 64); 305 case USB_TRANSFER_CONTROL: /* device specifies its own max size */ 306 return (size <= (low_speed ? 8 : 64)); 307 case USB_TRANSFER_BULK: /* device specifies its own max size */ 308 return (!low_speed && size <= 64); 309 } 310 return false; 311 } 313 312 /** 314 313 * @}
Note:
See TracChangeset
for help on using the changeset viewer.