Changeset 7265558 in mainline
- Timestamp:
- 2011-10-28T20:53:41Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 48ae3ef
- Parents:
- 83c3123
- Location:
- uspace
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/hc.c
r83c3123 r7265558 192 192 list_initialize(&instance->pending_batches); 193 193 194 ret =hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,194 hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11, 195 195 bandwidth_count_usb11); 196 CHECK_RET_RETURN(ret, "Failed to initialize generic driver: %s.\n",197 str_error(ret));198 196 instance->generic.private_data = instance; 199 197 instance->generic.schedule = hc_schedule; -
uspace/drv/bus/usb/uhci/hc.c
r83c3123 r7265558 192 192 "Device registers at %p (%zuB) accessible.\n", io, reg_size); 193 193 194 ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11, 194 ret = hc_init_mem_structures(instance); 195 CHECK_RET_RETURN(ret, 196 "Failed to initialize UHCI memory structures: %s.\n", 197 str_error(ret)); 198 199 #undef CHECK_RET_RETURN 200 201 hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11, 195 202 bandwidth_count_usb11); 196 CHECK_RET_RETURN(ret, "Failed to initialize HCD generic driver: %s.\n",197 str_error(ret));198 203 199 204 instance->generic.private_data = instance; 200 205 instance->generic.schedule = hc_schedule; 201 206 instance->generic.ep_add_hook = NULL; 202 203 #undef CHECK_RET_DEST_FUN_RETURN204 205 ret = hc_init_mem_structures(instance);206 if (ret != EOK) {207 usb_log_error(208 "Failed to initialize UHCI memory structures: %s.\n",209 str_error(ret));210 hcd_destroy(&instance->generic);211 return ret;212 }213 207 214 208 hc_init_hw(instance); -
uspace/lib/usbhost/include/usb/host/endpoint.h
r83c3123 r7265558 77 77 int endpoint_toggle_get(endpoint_t *instance); 78 78 void endpoint_toggle_set(endpoint_t *instance, int toggle); 79 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target); 79 80 static inline endpoint_t * endpoint_get_instance(link_t *item) 81 { 82 return list_get_instance(item, endpoint_t, link); 83 } 80 84 #endif 81 85 /** -
uspace/lib/usbhost/include/usb/host/hcd.h
r83c3123 r7265558 37 37 38 38 #include <assert.h> 39 #include <usbhc_iface.h> 39 40 #include <usb/host/usb_device_manager.h> 40 41 #include <usb/host/usb_endpoint_manager.h> 41 42 #include <usb/host/usb_transfer_batch.h> 42 #include <usbhc_iface.h>43 43 44 44 typedef struct hcd hcd_t; … … 53 53 }; 54 54 /*----------------------------------------------------------------------------*/ 55 static inline inthcd_init(hcd_t *hcd, size_t bandwidth,55 static inline void hcd_init(hcd_t *hcd, size_t bandwidth, 56 56 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t)) 57 57 { 58 58 assert(hcd); 59 59 usb_device_manager_init(&hcd->dev_manager); 60 return usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count); 61 } 62 /*----------------------------------------------------------------------------*/ 63 static inline void hcd_destroy(hcd_t *hcd) 64 { 65 usb_endpoint_manager_destroy(&hcd->ep_manager); 60 usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count); 66 61 } 67 62 /*----------------------------------------------------------------------------*/ -
uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h
r83c3123 r7265558 40 40 #define LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H 41 41 42 #include <stdlib.h> 43 #include <adt/hash_table.h> 42 #include <adt/list.h> 44 43 #include <fibril_synch.h> 45 44 #include <usb/usb.h> 45 46 46 #include <usb/host/endpoint.h> 47 47 48 48 #define BANDWIDTH_TOTAL_USB11 12000000 49 49 #define BANDWIDTH_AVAILABLE_USB11 ((BANDWIDTH_TOTAL_USB11 / 10) * 9) 50 #define ENDPOINT_LIST_COUNT 8 50 51 51 52 typedef struct usb_endpoint_manager { 52 hash_table_t ep_table;53 list_t endpoint_lists[ENDPOINT_LIST_COUNT]; 53 54 fibril_mutex_t guard; 54 55 size_t free_bw; -
uspace/lib/usbhost/src/endpoint.c
r83c3123 r7265558 133 133 instance->toggle = toggle; 134 134 } 135 /*----------------------------------------------------------------------------*/136 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target)137 {138 assert(instance);139 if (instance->address == target.address &&140 (instance->endpoint == target.endpoint || target.endpoint == 0))141 endpoint_toggle_set(instance, 0);142 }143 135 /** 144 136 * @} -
uspace/lib/usbhost/src/usb_endpoint_manager.c
r83c3123 r7265558 34 34 #include <usb/host/usb_endpoint_manager.h> 35 35 36 #define BUCKET_COUNT 7 37 #define MAX_KEYS (3) 38 39 static hash_index_t usb_hash(unsigned long key[]) 40 { 41 /* USB endpoints use 4 bits, thus ((key[0] << 4) | key[1]) 42 * produces unique value for every address.endpoint pair */ 43 return ((key[0] << 4) | key[1]) % BUCKET_COUNT; 44 } 45 /*----------------------------------------------------------------------------*/ 46 static int ep_compare(unsigned long key[], hash_count_t keys, link_t *item) 47 { 48 assert(item); 49 endpoint_t *ep = hash_table_get_instance(item, endpoint_t, link); 36 static inline bool ep_match(const endpoint_t *ep, 37 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 38 { 50 39 assert(ep); 51 bool match = true; 52 switch (keys) { 53 case 3: 54 match = match && 55 ((key[2] == ep->direction) 56 || (ep->direction == USB_DIRECTION_BOTH) 57 || (key[2] == USB_DIRECTION_BOTH)); 58 case 2: 59 match = match && (key[1] == (unsigned long)ep->endpoint); 60 case 1: 61 match = match && (key[0] == (unsigned long)ep->address); 62 break; 63 default: 64 match = false; 65 } 66 return match; 67 } 68 /*----------------------------------------------------------------------------*/ 69 static void ep_remove(link_t *item) 70 { 71 assert(item); 72 endpoint_t *ep = hash_table_get_instance(item, endpoint_t, link); 73 endpoint_destroy(ep); 74 } 75 /*----------------------------------------------------------------------------*/ 76 static void toggle_reset_filtered(link_t *item, void *arg) 77 { 78 assert(item); 79 endpoint_t *ep = hash_table_get_instance(item, endpoint_t, link); 80 const usb_target_t *target = arg; 81 endpoint_toggle_reset_filtered(ep, *target); 82 } 83 /*----------------------------------------------------------------------------*/ 84 static hash_table_operations_t op = { 85 .hash = usb_hash, 86 .compare = ep_compare, 87 .remove_callback = ep_remove, 88 }; 40 return 41 ((direction == ep->direction) 42 || (ep->direction == USB_DIRECTION_BOTH) 43 || (direction == USB_DIRECTION_BOTH)) 44 && (endpoint == ep->endpoint) 45 && (address == ep->address); 46 } 47 /*----------------------------------------------------------------------------*/ 48 static list_t * get_list(usb_endpoint_manager_t *instance, usb_address_t addr) 49 { 50 assert(instance); 51 return &instance->endpoint_lists[addr % ENDPOINT_LIST_COUNT]; 52 } 53 /*----------------------------------------------------------------------------*/ 54 static endpoint_t * find_locked(usb_endpoint_manager_t *instance, 55 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 56 { 57 assert(instance); 58 assert(fibril_mutex_is_locked(&instance->guard)); 59 list_foreach(*get_list(instance, address), iterator) { 60 endpoint_t *ep = endpoint_get_instance(iterator); 61 if (ep_match(ep, address, endpoint, direction)) 62 return ep; 63 } 64 return NULL; 65 } 89 66 /*----------------------------------------------------------------------------*/ 90 67 size_t bandwidth_count_usb11(usb_speed_t speed, usb_transfer_type_t type, … … 99 76 const unsigned packet_count = 100 77 (size + max_packet_size - 1) / max_packet_size; 101 /* TODO: It may be that ISO and INT transfers use only one data packet 102 * per transaction, but I did not find text in UB spec that confirms 103 * this */ 78 /* TODO: It may be that ISO and INT transfers use only one packet per 79 * transaction, but I did not find text in USB spec to confirm this */ 104 80 /* NOTE: All data packets will be considered to be max_packet_size */ 105 81 switch (speed) … … 138 114 instance->free_bw = available_bandwidth; 139 115 instance->bw_count = bw_count; 140 const bool ht = 141 hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op); 142 return ht ? EOK : ENOMEM; 143 } 144 /*----------------------------------------------------------------------------*/ 145 void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance) 146 { 147 hash_table_destroy(&instance->ep_table); 116 for (unsigned i = 0; i < ENDPOINT_LIST_COUNT; ++i) { 117 list_initialize(&instance->endpoint_lists[i]); 118 } 119 return EOK; 148 120 } 149 121 /*----------------------------------------------------------------------------*/ … … 164 136 } 165 137 166 unsigned long key[MAX_KEYS] = 167 {ep->address, ep->endpoint, ep->direction}; 168 169 const link_t *item = 170 hash_table_find(&instance->ep_table, key); 171 if (item != NULL) { 138 /* Check for existence */ 139 const endpoint_t *endpoint = 140 find_locked(instance, ep->address, ep->endpoint, ep->direction); 141 if (endpoint != NULL) { 172 142 fibril_mutex_unlock(&instance->guard); 173 143 return EEXISTS; 174 144 } 175 176 hash_table_insert(&instance->ep_table, key, &ep->link); 145 list_t *list = get_list(instance, ep->address); 146 list_append(&ep->link, list); 147 177 148 instance->free_bw -= ep->bandwidth; 178 149 fibril_mutex_unlock(&instance->guard); … … 184 155 { 185 156 assert(instance); 186 unsigned long key[MAX_KEYS] = {address, endpoint, direction};187 157 188 158 fibril_mutex_lock(&instance->guard); 189 link_t *item = hash_table_find(&instance->ep_table, key); 190 if (item == NULL) { 191 fibril_mutex_unlock(&instance->guard); 192 return EINVAL; 193 } 194 195 endpoint_t *ep = hash_table_get_instance(item, endpoint_t, link); 196 if (ep->active) { 197 fibril_mutex_unlock(&instance->guard); 198 return EBUSY; 199 } 200 201 instance->free_bw += ep->bandwidth; 202 hash_table_remove(&instance->ep_table, key, MAX_KEYS); 159 endpoint_t *ep = find_locked(instance, address, endpoint, direction); 160 if (ep != NULL) { 161 list_remove(&ep->link); 162 instance->free_bw += ep->bandwidth; 163 } 203 164 204 165 fibril_mutex_unlock(&instance->guard); 205 return EOK; 166 endpoint_destroy(ep); 167 return (ep != NULL) ? EOK : EINVAL; 206 168 } 207 169 /*----------------------------------------------------------------------------*/ … … 210 172 { 211 173 assert(instance); 212 unsigned long key[MAX_KEYS] = {address, endpoint, direction};213 174 214 175 fibril_mutex_lock(&instance->guard); 215 const link_t *item = hash_table_find(&instance->ep_table, key); 216 if (item == NULL) { 217 fibril_mutex_unlock(&instance->guard); 218 return NULL; 219 } 220 endpoint_t *ep = hash_table_get_instance(item, endpoint_t, link); 221 176 endpoint_t *ep = find_locked(instance, address, endpoint, direction); 222 177 fibril_mutex_unlock(&instance->guard); 178 223 179 return ep; 224 180 } … … 247 203 /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */ 248 204 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 205 fibril_mutex_lock(&instance->guard); 249 206 /* endpoint number is < 16, thus first byte is enough */ 250 usb_target_t reset_target = 251 { .address = target.address, data[4] }; 252 fibril_mutex_lock(&instance->guard); 253 hash_table_apply(&instance->ep_table, 254 toggle_reset_filtered, &reset_target); 207 list_foreach(*get_list(instance, target.address), it) { 208 endpoint_t *ep = endpoint_get_instance(it); 209 if ((ep->address == target.address) 210 && (ep->endpoint = data[4])) { 211 endpoint_toggle_set(ep,0); 212 } 213 } 255 214 fibril_mutex_unlock(&instance->guard); 256 215 } … … 259 218 case 0x9: /* Set Configuration */ 260 219 case 0x11: /* Set Interface */ 261 /* Recipient must be device */ 220 /* Recipient must be device, this resets all endpoints, 221 * In fact there should be no endpoints but EP 0 registered 222 * as different interfaces use different endpoints. */ 262 223 if ((data[0] & 0xf) == 0) { 263 usb_target_t reset_target =264 { .address = target.address, 0 };265 224 fibril_mutex_lock(&instance->guard); 266 hash_table_apply(&instance->ep_table, 267 toggle_reset_filtered, &reset_target); 225 list_foreach(*get_list(instance, target.address), it) { 226 endpoint_t *ep = endpoint_get_instance(it); 227 if (ep->address == target.address) { 228 endpoint_toggle_set(ep,0); 229 } 230 } 268 231 fibril_mutex_unlock(&instance->guard); 269 232 }
Note:
See TracChangeset
for help on using the changeset viewer.