Changeset 98fb010 in mainline
- Timestamp:
- 2011-10-16T19:33:47Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1f131fb9
- Parents:
- 721d4b6e (diff), f8dfb40 (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. - Location:
- uspace/drv/bus/usb/ohci
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/endpoint_list.c
r721d4b6e r98fb010 60 60 name, instance->list_head, instance->list_head_pa); 61 61 62 ed_init(instance->list_head, NULL );62 ed_init(instance->list_head, NULL, NULL); 63 63 list_initialize(&instance->endpoint_list); 64 64 fibril_mutex_initialize(&instance->guard); -
uspace/drv/bus/usb/ohci/hc.c
r721d4b6e r98fb010 565 565 566 566 /*Init HCCA */ 567 instance->hcca = malloc32(sizeof(hcca_t));567 instance->hcca = hcca_get(); 568 568 if (instance->hcca == NULL) 569 569 return ENOMEM; -
uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c
r721d4b6e r98fb010 34 34 #include "endpoint_descriptor.h" 35 35 36 static unsigned direc[3] = 37 { ED_STATUS_D_IN, ED_STATUS_D_OUT, ED_STATUS_D_TRANSFER }; 36 /** USB direction to OHCI values translation table. */ 37 static const uint32_t dir[] = { 38 [USB_DIRECTION_IN] = ED_STATUS_D_IN, 39 [USB_DIRECTION_OUT] = ED_STATUS_D_OUT, 40 [USB_DIRECTION_BOTH] = ED_STATUS_D_TD, 41 }; 38 42 39 void ed_init(ed_t *instance, endpoint_t *ep) 43 /** 44 * Initialize ED. 45 * 46 * @param instance ED structure to initialize. 47 * @param ep Driver endpoint to use. 48 * @param td TD to put in the list. 49 * 50 * If @param ep is NULL, dummy ED is initalized with only skip flag set. 51 */ 52 void ed_init(ed_t *instance, const endpoint_t *ep, const td_t *td) 40 53 { 41 54 assert(instance); 42 55 bzero(instance, sizeof(ed_t)); 56 43 57 if (ep == NULL) { 58 /* Mark as dead, used for dummy EDs at the beginning of 59 * endpoint lists. */ 44 60 instance->status = ED_STATUS_K_FLAG; 45 61 return; 46 62 } 47 assert(ep); 63 /* Non-dummy ED must have TD assigned */ 64 assert(td); 65 66 /* Status: address, endpoint nr, direction mask and max packet size. */ 48 67 instance->status = 0 49 68 | ((ep->address & ED_STATUS_FA_MASK) << ED_STATUS_FA_SHIFT) 50 69 | ((ep->endpoint & ED_STATUS_EN_MASK) << ED_STATUS_EN_SHIFT) 51 | ((dir ec[ep->direction] & ED_STATUS_D_MASK) << ED_STATUS_D_SHIFT)70 | ((dir[ep->direction] & ED_STATUS_D_MASK) << ED_STATUS_D_SHIFT) 52 71 | ((ep->max_packet_size & ED_STATUS_MPS_MASK) 53 72 << ED_STATUS_MPS_SHIFT); 54 73 55 74 /* Low speed flag */ 56 75 if (ep->speed == USB_SPEED_LOW) 57 76 instance->status |= ED_STATUS_S_FLAG; 77 78 /* Isochronous format flag */ 58 79 if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS) 59 80 instance->status |= ED_STATUS_F_FLAG; 60 81 82 /* Set TD to the list */ 83 const uintptr_t pa = addr_to_phys(td); 84 instance->td_head = pa & ED_TDHEAD_PTR_MASK; 85 instance->td_tail = pa & ED_TDTAIL_PTR_MASK; 86 87 /* Set toggle bit */ 61 88 if (ep->toggle) 62 89 instance->td_head |= ED_TDHEAD_TOGGLE_CARRY; 90 63 91 } 64 92 /** -
uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h
r721d4b6e r98fb010 45 45 #include "completion_codes.h" 46 46 47 /** 48 * OHCI Endpoint Descriptor representation. 49 * 50 * See OHCI spec. Chapter 4.2, page 16 (pdf page 30) for details */ 47 51 typedef struct ed { 52 /** 53 * Status field. 54 * 55 * See table 4-1, p. 17 OHCI spec (pdf page 31). 56 */ 48 57 volatile uint32_t status; 49 58 #define ED_STATUS_FA_MASK (0x7f) /* USB device address */ … … 51 60 #define ED_STATUS_EN_MASK (0xf) /* USB endpoint address */ 52 61 #define ED_STATUS_EN_SHIFT (7) 53 #define ED_STATUS_D_MASK (0x3) /* direction */62 #define ED_STATUS_D_MASK (0x3) /* Direction */ 54 63 #define ED_STATUS_D_SHIFT (11) 55 64 #define ED_STATUS_D_OUT (0x1) 56 65 #define ED_STATUS_D_IN (0x2) 57 #define ED_STATUS_D_T RANSFER (0x3)66 #define ED_STATUS_D_TD (0x3) /* Direction is specified by TD */ 58 67 59 #define ED_STATUS_S_FLAG (1 << 13) /* speed flag: 1 = low */60 #define ED_STATUS_K_FLAG (1 << 14) /* skip flag (no not execute this ED) */61 #define ED_STATUS_F_FLAG (1 << 15) /* format: 1 = isochronous*/62 #define ED_STATUS_MPS_MASK (0x3ff) /* max_packet_size*/68 #define ED_STATUS_S_FLAG (1 << 13) /* Speed flag: 1 = low */ 69 #define ED_STATUS_K_FLAG (1 << 14) /* Skip flag (no not execute this ED) */ 70 #define ED_STATUS_F_FLAG (1 << 15) /* Format: 1 = isochronous */ 71 #define ED_STATUS_MPS_MASK (0x3ff) /* Maximum packet size */ 63 72 #define ED_STATUS_MPS_SHIFT (16) 64 73 74 /** 75 * Pointer to the last TD. 76 * 77 * OHCI hw never changes this field and uses it only for a reference. 78 */ 65 79 volatile uint32_t td_tail; 66 80 #define ED_TDTAIL_PTR_MASK (0xfffffff0) 67 81 #define ED_TDTAIL_PTR_SHIFT (0) 68 82 83 /** 84 * Pointer to the first TD. 85 * 86 * Driver should not change this field if the ED is active. 87 * This field is updated by OHCI hw and points to the next TD 88 * to be executed. 89 */ 69 90 volatile uint32_t td_head; 70 91 #define ED_TDHEAD_PTR_MASK (0xfffffff0) … … 75 96 #define ED_TDHEAD_HALTED_FLAG (0x1) 76 97 98 /** 99 * Pointer to the next ED. 100 * 101 * Driver should not change this field on active EDs. 102 */ 77 103 volatile uint32_t next; 78 104 #define ED_NEXT_PTR_MASK (0xfffffff0) … … 80 106 } __attribute__((packed)) ed_t; 81 107 82 void ed_init(ed_t *instance, endpoint_t *ep);108 void ed_init(ed_t *instance, const endpoint_t *ep, const td_t *td); 83 109 84 static inline void ed_set_td(ed_t *instance, td_t *td) 110 /** 111 * Check for SKIP or HALTED flag being set. 112 * @param instance ED 113 * @return true if either SKIP or HALTED flag is set, false otherwise. 114 */ 115 static inline bool ed_inactive(const ed_t *instance) 85 116 { 86 117 assert(instance); 87 uintptr_t pa = addr_to_phys(td); 88 instance->td_head = 89 ((pa & ED_TDHEAD_PTR_MASK) 90 | (instance->td_head & ~ED_TDHEAD_PTR_MASK)); 118 return (instance->td_head & ED_TDHEAD_HALTED_FLAG) 119 || (instance->status & ED_STATUS_K_FLAG); 120 } 121 122 /** 123 * Check whether this ED contains TD to be executed. 124 * @param instance ED 125 * @return true if there are pending TDs, false otherwise. 126 */ 127 static inline bool ed_transfer_pending(const ed_t *instance) 128 { 129 assert(instance); 130 return (instance->td_head & ED_TDHEAD_PTR_MASK) 131 != (instance->td_tail & ED_TDTAIL_PTR_MASK); 132 } 133 134 /** 135 * Set the last element of TD list 136 * @param instance ED 137 * @param instance TD to set as the last item. 138 */ 139 static inline void ed_set_tail_td(ed_t *instance, const td_t *td) 140 { 141 assert(instance); 142 const uintptr_t pa = addr_to_phys(td); 91 143 instance->td_tail = pa & ED_TDTAIL_PTR_MASK; 92 144 } 93 145 94 static inline void ed_set_end_td(ed_t *instance, td_t *td) 95 { 96 assert(instance); 97 uintptr_t pa = addr_to_phys(td); 98 instance->td_tail = pa & ED_TDTAIL_PTR_MASK; 99 } 100 101 static inline void ed_append_ed(ed_t *instance, ed_t *next) 146 /** 147 * Set next ED in ED chain. 148 * @param instance ED to modify 149 * @param next ED to append 150 */ 151 static inline void ed_append_ed(ed_t *instance, const ed_t *next) 102 152 { 103 153 assert(instance); 104 154 assert(next); 105 uint32_t pa = addr_to_phys(next);155 const uint32_t pa = addr_to_phys(next); 106 156 assert((pa & ED_NEXT_PTR_MASK) << ED_NEXT_PTR_SHIFT == pa); 107 157 instance->next = pa; 108 158 } 109 159 110 static inline int ed_toggle_get(ed_t *instance) 160 /** 161 * Get toggle bit value stored in this ED 162 * @param instance ED 163 * @return Toggle bit value 164 */ 165 static inline int ed_toggle_get(const ed_t *instance) 111 166 { 112 167 assert(instance); … … 114 169 } 115 170 116 static inline void ed_toggle_set(ed_t *instance, int toggle) 171 /** 172 * Set toggle bit value stored in this ED 173 * @param instance ED 174 * @param toggle Toggle bit value 175 */ 176 static inline void ed_toggle_set(ed_t *instance, bool toggle) 117 177 { 118 178 assert(instance); 119 assert(toggle == 0 || toggle == 1); 120 if (toggle == 1) { 179 if (toggle) { 121 180 instance->td_head |= ED_TDHEAD_TOGGLE_CARRY; 122 181 } else { 123 /* clear halted flag when reseting toggle*/182 /* Clear halted flag when reseting toggle TODO: Why? */ 124 183 instance->td_head &= ~ED_TDHEAD_TOGGLE_CARRY; 125 184 instance->td_head &= ~ED_TDHEAD_HALTED_FLAG; -
uspace/drv/bus/usb/ohci/hw_struct/hcca.h
r721d4b6e r98fb010 36 36 37 37 #include <stdint.h> 38 #include <malloc.h> 38 39 39 40 /** Host controller communication area. … … 48 49 } __attribute__((packed, aligned)) hcca_t; 49 50 51 static inline void * hcca_get(void) 52 { 53 assert(sizeof(hcca_t) == 256); 54 return memalign(256, sizeof(hcca_t)); 55 } 50 56 #endif 51 57 /** -
uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c
r721d4b6e r98fb010 35 35 #include "transfer_descriptor.h" 36 36 37 static unsigned dp[3] = 38 { TD_STATUS_DP_IN, TD_STATUS_DP_OUT, TD_STATUS_DP_SETUP }; 39 static unsigned togg[2] = { TD_STATUS_T_0, TD_STATUS_T_1 }; 37 /** USB direction to OHCI TD values translation table */ 38 static const uint32_t dir[] = { 39 [USB_DIRECTION_IN] = TD_STATUS_DP_IN, 40 [USB_DIRECTION_OUT] = TD_STATUS_DP_OUT, 41 [USB_DIRECTION_BOTH] = TD_STATUS_DP_SETUP, 42 }; 40 43 41 void td_init(td_t *instance, 42 usb_direction_t dir, const void *buffer, size_t size, int toggle) 44 /** 45 * Initialize OHCI TD. 46 * @param instance TD structure to initialize. 47 * @param next Next TD in ED list. 48 * @param direction Used to determine PID, BOTH means setup PID. 49 * @param buffer Pointer to the first byte of transferred data. 50 * @param size Size of the buffer. 51 * @param toggle Toggle bit value, use 0/1 to set explicitly, 52 * any other value means that ED toggle will be used. 53 */ 54 void td_init(td_t *instance, const td_t *next, 55 usb_direction_t direction, const void *buffer, size_t size, int toggle) 43 56 { 44 57 assert(instance); 45 58 bzero(instance, sizeof(td_t)); 59 /* Set PID and Error code */ 46 60 instance->status = 0 47 | ((d p[dir] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)61 | ((dir[direction] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT) 48 62 | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT); 63 49 64 if (toggle == 0 || toggle == 1) { 50 instance->status |= togg[toggle] << TD_STATUS_T_SHIFT; 65 /* Set explicit toggle bit */ 66 instance->status |= TD_STATUS_T_USE_TD_FLAG; 67 instance->status |= toggle ? TD_STATUS_T_FLAG : 0; 51 68 } 69 70 /* Alow less data on input. */ 52 71 if (dir == USB_DIRECTION_IN) { 53 72 instance->status |= TD_STATUS_ROUND_FLAG; 54 73 } 74 55 75 if (buffer != NULL) { 56 76 assert(size != 0); … … 58 78 instance->be = addr_to_phys(buffer + size - 1); 59 79 } 80 81 instance->next = addr_to_phys(next) & TD_NEXT_PTR_MASK; 82 60 83 } 61 84 /** -
uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h
r721d4b6e r98fb010 37 37 #include <bool.h> 38 38 #include <stdint.h> 39 39 40 #include "../utils/malloc32.h" 40 41 41 #include "completion_codes.h" 42 42 … … 46 46 #define OHCI_TD_MAX_TRANSFER (4 * 1024) 47 47 48 /** 49 * Transfer Descriptor representation. 50 * 51 * See OHCI spec chapter 4.3.1 General Transfer Descriptor on page 19 52 * (pdf page 33) for details. 53 */ 48 54 typedef struct td { 55 /** Status field. Do not touch on active TDs. */ 49 56 volatile uint32_t status; 50 57 #define TD_STATUS_ROUND_FLAG (1 << 18) 51 #define TD_STATUS_DP_MASK (0x3) /* direction/PID */58 #define TD_STATUS_DP_MASK (0x3) /* Direction/PID */ 52 59 #define TD_STATUS_DP_SHIFT (19) 53 60 #define TD_STATUS_DP_SETUP (0x0) 54 61 #define TD_STATUS_DP_OUT (0x1) 55 62 #define TD_STATUS_DP_IN (0x2) 56 #define TD_STATUS_DI_MASK (0x7) /* delay interrupt, wait DI frames before int*/63 #define TD_STATUS_DI_MASK (0x7) /* Delay interrupt, wait n frames before irq */ 57 64 #define TD_STATUS_DI_SHIFT (21) 58 65 #define TD_STATUS_DI_NO_INTERRUPT (0x7) 59 #define TD_STATUS_T_MASK (0x3) /* data toggle 1x = use ED toggle carry */ 60 #define TD_STATUS_T_SHIFT (24) 61 #define TD_STATUS_T_0 (0x2) 62 #define TD_STATUS_T_1 (0x3) 63 #define TD_STATUS_T_ED (0) 64 #define TD_STATUS_EC_MASK (0x3) /* error count */ 66 #define TD_STATUS_T_FLAG (1 << 24) /* Explicit toggle bit value for this TD */ 67 #define TD_STATUS_T_USE_TD_FLAG (1 << 25) /* 1 = use bit 24 as toggle bit */ 68 #define TD_STATUS_EC_MASK (0x3) /* Error count */ 65 69 #define TD_STATUS_EC_SHIFT (26) 66 #define TD_STATUS_CC_MASK (0xf) /* condition code */70 #define TD_STATUS_CC_MASK (0xf) /* Condition code */ 67 71 #define TD_STATUS_CC_SHIFT (28) 68 72 69 volatile uint32_t cbp; /* current buffer ptr, data to be transfered */ 73 /** 74 * Current buffer pointer. 75 * Phys address of the first byte to be transferred. */ 76 volatile uint32_t cbp; 77 78 /** Pointer to the next TD in chain. 16-byte aligned. */ 70 79 volatile uint32_t next; 71 80 #define TD_NEXT_PTR_MASK (0xfffffff0) 72 81 #define TD_NEXT_PTR_SHIFT (0) 73 82 74 volatile uint32_t be; /* buffer end, address of the last byte */ 83 /** 84 * Buffer end. 85 * Phys address of the last byte of the transfer. 86 * @note this does not have to be on the same page as cbp. 87 */ 88 volatile uint32_t be; 75 89 } __attribute__((packed)) td_t; 76 90 77 void td_init(td_t *instance, 91 void td_init(td_t *instance, const td_t *next, 78 92 usb_direction_t dir, const void *buffer, size_t size, int toggle); 79 93 80 inline static void td_set_next(td_t *instance, td_t *next) 94 /** 95 * Check TD for completion. 96 * @param instance TD structure. 97 * @return true if the TD was accessed and processed by hw, false otherwise. 98 */ 99 inline static bool td_is_finished(const td_t *instance) 81 100 { 82 101 assert(instance); 83 instance->next = addr_to_phys(next) & TD_NEXT_PTR_MASK; 84 } 85 86 inline static bool td_is_finished(td_t *instance) 87 { 88 assert(instance); 89 int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK; 90 /* something went wrong, error code is set */ 102 const int cc = 103 (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK; 104 /* This value is changed on transfer completion, 105 * either to CC_NOERROR or and error code. 106 * See OHCI spec 4.3.1.3.5 p. 23 (pdf 37) */ 91 107 if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2) { 92 return true;93 }94 /* everything done */95 if (cc == CC_NOERROR && instance->cbp == 0) {96 108 return true; 97 109 } … … 99 111 } 100 112 101 static inline int td_error(td_t *instance) 113 /** 114 * Get error code that indicates transfer status. 115 * @param instance TD structure. 116 * @return Error code. 117 */ 118 static inline int td_error(const td_t *instance) 102 119 { 103 120 assert(instance); 104 int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK; 121 const int cc = 122 (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK; 105 123 return cc_to_rc(cc); 106 124 } 107 125 126 /** 127 * Get remaining portion of buffer to be read/written 128 * @param instance TD structure 129 * @return size of remaining buffer. 130 */ 108 131 static inline size_t td_remain_size(td_t *instance) 109 132 { 110 133 assert(instance); 134 /* Current buffer pointer is cleared on successful transfer */ 111 135 if (instance->cbp == 0) 112 136 return 0; 137 /* Buffer end points to the last byte of transfer buffer, so add 1 */ 113 138 return instance->be - instance->cbp + 1; 114 139 } -
uspace/drv/bus/usb/ohci/ohci_batch.c
r721d4b6e r98fb010 163 163 ohci_batch->ed->td_tail, ohci_batch->ed->next); 164 164 165 size_t i = 0; 166 for (; i < ohci_batch->td_count; ++i) { 165 if (!ed_inactive(ohci_batch->ed) && ed_transfer_pending(ohci_batch->ed)) 166 return false; 167 168 /* Now we may be sure that either the ED is inactive because of errors 169 * or all transfer descriptors completed successfully */ 170 171 /* Assume all data got through */ 172 ohci_batch->usb_batch->transfered_size = 173 ohci_batch->usb_batch->buffer_size; 174 175 /* Assume we will leave the last(unused) TD behind */ 176 ohci_batch->leave_td = ohci_batch->td_count; 177 178 /* Check all TDs */ 179 for (size_t i = 0; i < ohci_batch->td_count; ++i) { 167 180 assert(ohci_batch->tds[i] != NULL); 168 181 usb_log_debug("TD %zu: %08x:%08x:%08x:%08x.\n", i, 169 182 ohci_batch->tds[i]->status, ohci_batch->tds[i]->cbp, 170 183 ohci_batch->tds[i]->next, ohci_batch->tds[i]->be); 171 if (!td_is_finished(ohci_batch->tds[i])) { 172 return false; 173 } 184 185 /* If the TD got all its data through, it will report 0 bytes 186 * remain, the sole exception is INPUT with data rounding flag 187 * (short), i.e. every INPUT. Nice thing is that short packets 188 * will correctly report remaining data, thus making 189 * this computation correct (short packets need to be produced 190 * by the last TD) 191 * NOTE: This also works for CONTROL transfer as 192 * the first TD will return 0 remain. 193 * NOTE: Short packets don't break the assumption that 194 * we leave the very last(unused) TD behind. 195 */ 196 ohci_batch->usb_batch->transfered_size 197 -= td_remain_size(ohci_batch->tds[i]); 198 174 199 ohci_batch->usb_batch->error = td_error(ohci_batch->tds[i]); 175 200 if (ohci_batch->usb_batch->error != EOK) { … … 177 202 ohci_batch->usb_batch, i, 178 203 ohci_batch->tds[i]->status); 179 /* Make sure TD queue is empty (one TD), 180 * ED should be marked as halted */ 181 ohci_batch->ed->td_tail = 182 (ohci_batch->ed->td_head & ED_TDTAIL_PTR_MASK); 183 ++i; 204 205 /* ED should be stopped because of errors */ 206 assert((ohci_batch->ed->td_head & ED_TDHEAD_HALTED_FLAG) != 0); 207 208 /* Now we have a problem: we don't know what TD 209 * the head pointer points to, the retiring rules 210 * described in specs say it should be the one after 211 * the failed one so set the tail pointer accordingly. 212 * It will be the one TD we leave behind. 213 */ 214 ohci_batch->leave_td = i + 1; 215 216 /* Check TD assumption */ 217 const uint32_t pa = addr_to_phys( 218 ohci_batch->tds[ohci_batch->leave_td]); 219 assert((ohci_batch->ed->td_head & ED_TDTAIL_PTR_MASK) 220 == pa); 221 222 ed_set_tail_td(ohci_batch->ed, 223 ohci_batch->tds[ohci_batch->leave_td]); 224 225 /* Clear possible ED HALT */ 226 ohci_batch->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG; 184 227 break; 185 228 } 186 229 } 187 188 assert(i <= ohci_batch->td_count);189 ohci_batch->leave_td = i; 190 230 assert(ohci_batch->usb_batch->transfered_size <= 231 ohci_batch->usb_batch->buffer_size); 232 233 /* Store the remaining TD */ 191 234 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep); 192 235 assert(ohci_ep); 193 236 ohci_ep->td = ohci_batch->tds[ohci_batch->leave_td]; 194 assert(i > 0); 195 ohci_batch->usb_batch->transfered_size = 196 ohci_batch->usb_batch->buffer_size; 197 for (--i;i < ohci_batch->td_count; ++i) { 198 ohci_batch->usb_batch->transfered_size 199 -= td_remain_size(ohci_batch->tds[i]); 200 } 201 202 /* Clear possible ED HALT */ 203 ohci_batch->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG; 204 /* just make sure that we are leaving the right TD behind */ 237 238 /* Make sure that we are leaving the right TD behind */ 205 239 const uint32_t pa = addr_to_phys(ohci_ep->td); 206 240 assert(pa == (ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK)); … … 217 251 { 218 252 assert(ohci_batch); 219 ed_set_ end_td(ohci_batch->ed, ohci_batch->tds[ohci_batch->td_count]);253 ed_set_tail_td(ohci_batch->ed, ohci_batch->tds[ohci_batch->td_count]); 220 254 } 221 255 /*----------------------------------------------------------------------------*/ … … 247 281 const usb_direction_t status_dir = reverse_dir[dir]; 248 282 249 /* setup stage */250 td_init( ohci_batch->tds[0], USB_DIRECTION_BOTH, buffer,251 ohci_batch->usb_batch->setup_size, toggle);252 td_set_next(ohci_batch->tds[0], ohci_batch->tds[1]);283 /* Setup stage */ 284 td_init( 285 ohci_batch->tds[0], ohci_batch->tds[1], USB_DIRECTION_BOTH, 286 buffer, ohci_batch->usb_batch->setup_size, toggle); 253 287 usb_log_debug("Created CONTROL SETUP TD: %08x:%08x:%08x:%08x.\n", 254 288 ohci_batch->tds[0]->status, ohci_batch->tds[0]->cbp, … … 256 290 buffer += ohci_batch->usb_batch->setup_size; 257 291 258 /* data stage */292 /* Data stage */ 259 293 size_t td_current = 1; 260 294 size_t remain_size = ohci_batch->usb_batch->buffer_size; … … 265 299 toggle = 1 - toggle; 266 300 267 td_init(ohci_batch->tds[td_current], data_dir, buffer, 268 transfer_size, toggle); 269 td_set_next(ohci_batch->tds[td_current], 270 ohci_batch->tds[td_current + 1]); 301 td_init(ohci_batch->tds[td_current], 302 ohci_batch->tds[td_current + 1], 303 data_dir, buffer, transfer_size, toggle); 271 304 usb_log_debug("Created CONTROL DATA TD: %08x:%08x:%08x:%08x.\n", 272 305 ohci_batch->tds[td_current]->status, … … 281 314 } 282 315 283 /* status stage */316 /* Status stage */ 284 317 assert(td_current == ohci_batch->td_count - 1); 285 td_init(ohci_batch->tds[td_current], status_dir, NULL, 0, 1); 286 td_set_next(ohci_batch->tds[td_current], 287 ohci_batch->tds[td_current + 1]); 318 td_init(ohci_batch->tds[td_current], ohci_batch->tds[td_current + 1], 319 status_dir, NULL, 0, 1); 288 320 usb_log_debug("Created CONTROL STATUS TD: %08x:%08x:%08x:%08x.\n", 289 321 ohci_batch->tds[td_current]->status, … … 323 355 ? OHCI_TD_MAX_TRANSFER : remain_size; 324 356 325 td_init(ohci_batch->tds[td_current], dir, buffer, 326 transfer_size, -1); 327 td_set_next(ohci_batch->tds[td_current], 328 ohci_batch->tds[td_current + 1]); 357 td_init( 358 ohci_batch->tds[td_current], ohci_batch->tds[td_current + 1], 359 dir, buffer, transfer_size, -1); 329 360 330 361 usb_log_debug("Created DATA TD: %08x:%08x:%08x:%08x.\n", -
uspace/drv/bus/usb/ohci/ohci_endpoint.c
r721d4b6e r98fb010 102 102 } 103 103 104 ed_init(ohci_ep->ed, ep); 105 ed_set_td(ohci_ep->ed, ohci_ep->td); 104 ed_init(ohci_ep->ed, ep, ohci_ep->td); 106 105 endpoint_set_hc_data( 107 106 ep, ohci_ep, ohci_endpoint_fini, ohci_ep_toggle_get, ohci_ep_toggle_set); -
uspace/drv/bus/usb/ohci/root_hub.c
r721d4b6e r98fb010 35 35 #include <errno.h> 36 36 #include <str_error.h> 37 #include <fibril_synch.h> 37 38 38 39 #include <usb/debug.h> 40 #include <usb/dev/request.h> 41 #include <usb/classes/hub.h> 39 42 40 43 #include "root_hub.h" … … 43 46 #include <usb/dev/driver.h> 44 47 #include "ohci_regs.h" 45 46 #include <usb/dev/request.h>47 #include <usb/classes/hub.h>48 48 49 49 /** … … 108 108 static void create_serialized_hub_descriptor(rh_t *instance); 109 109 static void rh_init_descriptors(rh_t *instance); 110 static uint16_t create_interrupt_mask(rh_t *instance); 111 static int get_status(rh_t *instance, usb_transfer_batch_t *request); 112 static int get_descriptor(rh_t *instance, usb_transfer_batch_t *request); 113 static int set_feature(rh_t *instance, usb_transfer_batch_t *request); 114 static int clear_feature(rh_t *instance, usb_transfer_batch_t *request); 115 static int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port); 116 static int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port); 110 static uint16_t create_interrupt_mask(const rh_t *instance); 111 static int get_status(const rh_t *instance, usb_transfer_batch_t *request); 112 static int get_descriptor(const rh_t *instance, usb_transfer_batch_t *request); 113 static int set_feature(const rh_t *instance, usb_transfer_batch_t *request); 114 static int clear_feature(const rh_t *instance, usb_transfer_batch_t *request); 115 static int set_feature_port( 116 const rh_t *instance, uint16_t feature, uint16_t port); 117 static int clear_feature_port( 118 const rh_t *instance, uint16_t feature, uint16_t port); 117 119 static int control_request(rh_t *instance, usb_transfer_batch_t *request); 118 120 static inline void interrupt_request( … … 153 155 instance->unfinished_interrupt_transfer = NULL; 154 156 155 #if defOHCI_POWER_SWITCH_no157 #if defined OHCI_POWER_SWITCH_no 156 158 /* Set port power mode to no power-switching. (always on) */ 157 159 instance->registers->rh_desc_a |= RHDA_NPS_FLAG; 160 158 161 /* Set to no over-current reporting */ 159 162 instance->registers->rh_desc_a |= RHDA_NOCP_FLAG; 163 160 164 #elif defined OHCI_POWER_SWITCH_ganged 161 165 /* Set port power mode to no ganged power-switching. */ … … 163 167 instance->registers->rh_desc_a &= ~RHDA_PSM_FLAG; 164 168 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER; 169 165 170 /* Set to global over-current */ 166 171 instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG; … … 174 179 instance->registers->rh_desc_b &= (RHDB_PCC_MASK << RHDB_PCC_SHIFT); 175 180 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER; 181 176 182 /* Return control to per port state */ 177 183 instance->registers->rh_desc_b |= 178 184 ((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT; 185 179 186 /* Set per port over-current */ 180 187 instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG; … … 182 189 #endif 183 190 191 fibril_mutex_initialize(&instance->guard); 184 192 rh_init_descriptors(instance); 185 193 … … 209 217 case USB_TRANSFER_INTERRUPT: 210 218 usb_log_debug("Root hub got INTERRUPT packet\n"); 219 fibril_mutex_lock(&instance->guard); 220 assert(instance->unfinished_interrupt_transfer == NULL); 211 221 const uint16_t mask = create_interrupt_mask(instance); 212 222 if (mask == 0) { 213 223 usb_log_debug("No changes..\n"); 214 assert(instance->unfinished_interrupt_transfer == NULL);215 224 instance->unfinished_interrupt_transfer = request; 225 fibril_mutex_unlock(&instance->guard); 216 226 return; 217 227 } 218 228 usb_log_debug("Processing changes...\n"); 219 229 interrupt_request(request, mask, instance->interrupt_mask_size); 230 fibril_mutex_unlock(&instance->guard); 220 231 break; 221 232 … … 237 248 assert(instance); 238 249 239 if (!instance->unfinished_interrupt_transfer) 240 return; 241 242 usb_log_debug("Finalizing interrupt transfer\n"); 243 const uint16_t mask = create_interrupt_mask(instance); 244 interrupt_request(instance->unfinished_interrupt_transfer, 245 mask, instance->interrupt_mask_size); 246 usb_transfer_batch_dispose(instance->unfinished_interrupt_transfer); 247 248 instance->unfinished_interrupt_transfer = NULL; 250 fibril_mutex_lock(&instance->guard); 251 if (instance->unfinished_interrupt_transfer) { 252 usb_log_debug("Finalizing interrupt transfer\n"); 253 const uint16_t mask = create_interrupt_mask(instance); 254 interrupt_request(instance->unfinished_interrupt_transfer, 255 mask, instance->interrupt_mask_size); 256 usb_transfer_batch_dispose( 257 instance->unfinished_interrupt_transfer); 258 instance->unfinished_interrupt_transfer = NULL; 259 } 260 fibril_mutex_unlock(&instance->guard); 249 261 } 250 262 /*----------------------------------------------------------------------------*/ … … 342 354 * @return Mask of changes. 343 355 */ 344 uint16_t create_interrupt_mask( rh_t *instance)356 uint16_t create_interrupt_mask(const rh_t *instance) 345 357 { 346 358 assert(instance); … … 372 384 * @return error code 373 385 */ 374 int get_status( rh_t *instance, usb_transfer_batch_t *request)386 int get_status(const rh_t *instance, usb_transfer_batch_t *request) 375 387 { 376 388 assert(instance); … … 418 430 * @return Error code 419 431 */ 420 int get_descriptor( rh_t *instance, usb_transfer_batch_t *request)432 int get_descriptor(const rh_t *instance, usb_transfer_batch_t *request) 421 433 { 422 434 assert(instance); … … 496 508 * @return error code 497 509 */ 498 int set_feature_port( rh_t *instance, uint16_t feature, uint16_t port)510 int set_feature_port(const rh_t *instance, uint16_t feature, uint16_t port) 499 511 { 500 512 assert(instance); … … 535 547 * @return error code 536 548 */ 537 int clear_feature_port( rh_t *instance, uint16_t feature, uint16_t port)549 int clear_feature_port(const rh_t *instance, uint16_t feature, uint16_t port) 538 550 { 539 551 assert(instance); … … 592 604 * @return error code 593 605 */ 594 int set_feature( rh_t *instance, usb_transfer_batch_t *request)606 int set_feature(const rh_t *instance, usb_transfer_batch_t *request) 595 607 { 596 608 assert(instance); … … 628 640 * @return error code 629 641 */ 630 int clear_feature( rh_t *instance, usb_transfer_batch_t *request)642 int clear_feature(const rh_t *instance, usb_transfer_batch_t *request) 631 643 { 632 644 assert(instance); … … 635 647 const usb_device_request_setup_packet_t *setup_request = 636 648 (usb_device_request_setup_packet_t *) request->setup_buffer; 649 637 650 request->transfered_size = 0; 651 638 652 switch (setup_request->request_type) 639 653 { … … 647 661 /* 648 662 * Chapter 11.16.2 specifies that only C_HUB_LOCAL_POWER and 649 * C_HUB_OVER_CURRENT are supported. C_HUB_OVER_CURRENT is represented 650 * by OHCI RHS_OCIC_FLAG. C_HUB_LOCAL_POWER is not supported 663 * C_HUB_OVER_CURRENT are supported. 664 * C_HUB_OVER_CURRENT is represented by OHCI RHS_OCIC_FLAG. 665 * C_HUB_LOCAL_POWER is not supported 651 666 * as root hubs do not support local power status feature. 652 667 * (OHCI pg. 127) */ … … 720 735 "additional data\n"); 721 736 return clear_feature(instance, request); 737 722 738 case USB_DEVREQ_SET_FEATURE: 723 739 usb_log_debug2("Processing request without " -
uspace/drv/bus/usb/ohci/root_hub.h
r721d4b6e r98fb010 47 47 */ 48 48 typedef struct rh { 49 fibril_mutex_t guard; 49 50 /** pointer to ohci driver registers */ 50 51 ohci_regs_t *registers; -
uspace/drv/bus/usb/ohci/utils/malloc32.h
r721d4b6e r98fb010 41 41 #include <as.h> 42 42 43 /* Generic TDs and EDs require 16byte alignment, 44 * Isochronous TD require 32byte alignment, 45 * buffers do not have to be aligned. 46 */ 47 #define OHCI_ALIGN 32 48 43 49 /** Get physical address translation 44 50 * … … 62 68 */ 63 69 static inline void * malloc32(size_t size) 64 { return memalign( size, size); }70 { return memalign(OHCI_ALIGN, size); } 65 71 /*----------------------------------------------------------------------------*/ 66 72 /** Physical mallocator simulator
Note:
See TracChangeset
for help on using the changeset viewer.