Changes in / [98fb010:721d4b6e] in mainline
- Location:
- uspace/drv/bus/usb/ohci
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/endpoint_list.c
r98fb010 r721d4b6e 60 60 name, instance->list_head, instance->list_head_pa); 61 61 62 ed_init(instance->list_head, NULL , NULL);62 ed_init(instance->list_head, NULL); 63 63 list_initialize(&instance->endpoint_list); 64 64 fibril_mutex_initialize(&instance->guard); -
uspace/drv/bus/usb/ohci/hc.c
r98fb010 r721d4b6e 565 565 566 566 /*Init HCCA */ 567 instance->hcca = hcca_get();567 instance->hcca = malloc32(sizeof(hcca_t)); 568 568 if (instance->hcca == NULL) 569 569 return ENOMEM; -
uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c
r98fb010 r721d4b6e 34 34 #include "endpoint_descriptor.h" 35 35 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 }; 36 static unsigned direc[3] = 37 { ED_STATUS_D_IN, ED_STATUS_D_OUT, ED_STATUS_D_TRANSFER }; 42 38 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) 39 void ed_init(ed_t *instance, endpoint_t *ep) 53 40 { 54 41 assert(instance); 55 42 bzero(instance, sizeof(ed_t)); 56 57 43 if (ep == NULL) { 58 /* Mark as dead, used for dummy EDs at the beginning of59 * endpoint lists. */60 44 instance->status = ED_STATUS_K_FLAG; 61 45 return; 62 46 } 63 /* Non-dummy ED must have TD assigned */ 64 assert(td); 65 66 /* Status: address, endpoint nr, direction mask and max packet size. */ 47 assert(ep); 67 48 instance->status = 0 68 49 | ((ep->address & ED_STATUS_FA_MASK) << ED_STATUS_FA_SHIFT) 69 50 | ((ep->endpoint & ED_STATUS_EN_MASK) << ED_STATUS_EN_SHIFT) 70 | ((dir [ep->direction] & ED_STATUS_D_MASK) << ED_STATUS_D_SHIFT)51 | ((direc[ep->direction] & ED_STATUS_D_MASK) << ED_STATUS_D_SHIFT) 71 52 | ((ep->max_packet_size & ED_STATUS_MPS_MASK) 72 53 << ED_STATUS_MPS_SHIFT); 73 54 74 /* Low speed flag */ 55 75 56 if (ep->speed == USB_SPEED_LOW) 76 57 instance->status |= ED_STATUS_S_FLAG; 77 78 /* Isochronous format flag */79 58 if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS) 80 59 instance->status |= ED_STATUS_F_FLAG; 81 60 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 */88 61 if (ep->toggle) 89 62 instance->td_head |= ED_TDHEAD_TOGGLE_CARRY; 90 91 63 } 92 64 /** -
uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h
r98fb010 r721d4b6e 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 */51 47 typedef struct ed { 52 /**53 * Status field.54 *55 * See table 4-1, p. 17 OHCI spec (pdf page 31).56 */57 48 volatile uint32_t status; 58 49 #define ED_STATUS_FA_MASK (0x7f) /* USB device address */ … … 60 51 #define ED_STATUS_EN_MASK (0xf) /* USB endpoint address */ 61 52 #define ED_STATUS_EN_SHIFT (7) 62 #define ED_STATUS_D_MASK (0x3) /* Direction */53 #define ED_STATUS_D_MASK (0x3) /* direction */ 63 54 #define ED_STATUS_D_SHIFT (11) 64 55 #define ED_STATUS_D_OUT (0x1) 65 56 #define ED_STATUS_D_IN (0x2) 66 #define ED_STATUS_D_T D (0x3) /* Direction is specified by TD */57 #define ED_STATUS_D_TRANSFER (0x3) 67 58 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*/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*/ 72 63 #define ED_STATUS_MPS_SHIFT (16) 73 64 74 /**75 * Pointer to the last TD.76 *77 * OHCI hw never changes this field and uses it only for a reference.78 */79 65 volatile uint32_t td_tail; 80 66 #define ED_TDTAIL_PTR_MASK (0xfffffff0) 81 67 #define ED_TDTAIL_PTR_SHIFT (0) 82 68 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 TD88 * to be executed.89 */90 69 volatile uint32_t td_head; 91 70 #define ED_TDHEAD_PTR_MASK (0xfffffff0) … … 96 75 #define ED_TDHEAD_HALTED_FLAG (0x1) 97 76 98 /**99 * Pointer to the next ED.100 *101 * Driver should not change this field on active EDs.102 */103 77 volatile uint32_t next; 104 78 #define ED_NEXT_PTR_MASK (0xfffffff0) … … 106 80 } __attribute__((packed)) ed_t; 107 81 108 void ed_init(ed_t *instance, const endpoint_t *ep, const td_t *td);82 void ed_init(ed_t *instance, endpoint_t *ep); 109 83 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) 84 static inline void ed_set_td(ed_t *instance, td_t *td) 116 85 { 117 86 assert(instance); 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); 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)); 143 91 instance->td_tail = pa & ED_TDTAIL_PTR_MASK; 144 92 } 145 93 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) 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) 152 102 { 153 103 assert(instance); 154 104 assert(next); 155 constuint32_t pa = addr_to_phys(next);105 uint32_t pa = addr_to_phys(next); 156 106 assert((pa & ED_NEXT_PTR_MASK) << ED_NEXT_PTR_SHIFT == pa); 157 107 instance->next = pa; 158 108 } 159 109 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) 110 static inline int ed_toggle_get(ed_t *instance) 166 111 { 167 112 assert(instance); … … 169 114 } 170 115 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) 116 static inline void ed_toggle_set(ed_t *instance, int toggle) 177 117 { 178 118 assert(instance); 179 if (toggle) { 119 assert(toggle == 0 || toggle == 1); 120 if (toggle == 1) { 180 121 instance->td_head |= ED_TDHEAD_TOGGLE_CARRY; 181 122 } else { 182 /* Clear halted flag when reseting toggle TODO: Why?*/123 /* clear halted flag when reseting toggle */ 183 124 instance->td_head &= ~ED_TDHEAD_TOGGLE_CARRY; 184 125 instance->td_head &= ~ED_TDHEAD_HALTED_FLAG; -
uspace/drv/bus/usb/ohci/hw_struct/hcca.h
r98fb010 r721d4b6e 36 36 37 37 #include <stdint.h> 38 #include <malloc.h>39 38 40 39 /** Host controller communication area. … … 49 48 } __attribute__((packed, aligned)) hcca_t; 50 49 51 static inline void * hcca_get(void)52 {53 assert(sizeof(hcca_t) == 256);54 return memalign(256, sizeof(hcca_t));55 }56 50 #endif 57 51 /** -
uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c
r98fb010 r721d4b6e 35 35 #include "transfer_descriptor.h" 36 36 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 }; 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 }; 43 40 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) 41 void td_init(td_t *instance, 42 usb_direction_t dir, const void *buffer, size_t size, int toggle) 56 43 { 57 44 assert(instance); 58 45 bzero(instance, sizeof(td_t)); 59 /* Set PID and Error code */60 46 instance->status = 0 61 | ((d ir[direction] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)47 | ((dp[dir] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT) 62 48 | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT); 63 64 49 if (toggle == 0 || toggle == 1) { 65 /* Set explicit toggle bit */ 66 instance->status |= TD_STATUS_T_USE_TD_FLAG; 67 instance->status |= toggle ? TD_STATUS_T_FLAG : 0; 50 instance->status |= togg[toggle] << TD_STATUS_T_SHIFT; 68 51 } 69 70 /* Alow less data on input. */71 52 if (dir == USB_DIRECTION_IN) { 72 53 instance->status |= TD_STATUS_ROUND_FLAG; 73 54 } 74 75 55 if (buffer != NULL) { 76 56 assert(size != 0); … … 78 58 instance->be = addr_to_phys(buffer + size - 1); 79 59 } 80 81 instance->next = addr_to_phys(next) & TD_NEXT_PTR_MASK;82 83 60 } 84 61 /** -
uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h
r98fb010 r721d4b6e 37 37 #include <bool.h> 38 38 #include <stdint.h> 39 #include "../utils/malloc32.h" 39 40 40 #include "../utils/malloc32.h"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 1952 * (pdf page 33) for details.53 */54 48 typedef struct td { 55 /** Status field. Do not touch on active TDs. */56 49 volatile uint32_t status; 57 50 #define TD_STATUS_ROUND_FLAG (1 << 18) 58 #define TD_STATUS_DP_MASK (0x3) /* Direction/PID */51 #define TD_STATUS_DP_MASK (0x3) /* direction/PID */ 59 52 #define TD_STATUS_DP_SHIFT (19) 60 53 #define TD_STATUS_DP_SETUP (0x0) 61 54 #define TD_STATUS_DP_OUT (0x1) 62 55 #define TD_STATUS_DP_IN (0x2) 63 #define TD_STATUS_DI_MASK (0x7) /* Delay interrupt, wait n frames before irq*/56 #define TD_STATUS_DI_MASK (0x7) /* delay interrupt, wait DI frames before int */ 64 57 #define TD_STATUS_DI_SHIFT (21) 65 58 #define TD_STATUS_DI_NO_INTERRUPT (0x7) 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 */ 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 */ 69 65 #define TD_STATUS_EC_SHIFT (26) 70 #define TD_STATUS_CC_MASK (0xf) /* Condition code */66 #define TD_STATUS_CC_MASK (0xf) /* condition code */ 71 67 #define TD_STATUS_CC_SHIFT (28) 72 68 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. */ 69 volatile uint32_t cbp; /* current buffer ptr, data to be transfered */ 79 70 volatile uint32_t next; 80 71 #define TD_NEXT_PTR_MASK (0xfffffff0) 81 72 #define TD_NEXT_PTR_SHIFT (0) 82 73 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; 74 volatile uint32_t be; /* buffer end, address of the last byte */ 89 75 } __attribute__((packed)) td_t; 90 76 91 void td_init(td_t *instance, const td_t *next,77 void td_init(td_t *instance, 92 78 usb_direction_t dir, const void *buffer, size_t size, int toggle); 93 79 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) 80 inline static void td_set_next(td_t *instance, td_t *next) 100 81 { 101 82 assert(instance); 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) */ 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 */ 107 91 if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2) { 92 return true; 93 } 94 /* everything done */ 95 if (cc == CC_NOERROR && instance->cbp == 0) { 108 96 return true; 109 97 } … … 111 99 } 112 100 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) 101 static inline int td_error(td_t *instance) 119 102 { 120 103 assert(instance); 121 const int cc = 122 (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK; 104 int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK; 123 105 return cc_to_rc(cc); 124 106 } 125 107 126 /**127 * Get remaining portion of buffer to be read/written128 * @param instance TD structure129 * @return size of remaining buffer.130 */131 108 static inline size_t td_remain_size(td_t *instance) 132 109 { 133 110 assert(instance); 134 /* Current buffer pointer is cleared on successful transfer */135 111 if (instance->cbp == 0) 136 112 return 0; 137 /* Buffer end points to the last byte of transfer buffer, so add 1 */138 113 return instance->be - instance->cbp + 1; 139 114 } -
uspace/drv/bus/usb/ohci/ohci_batch.c
r98fb010 r721d4b6e 163 163 ohci_batch->ed->td_tail, ohci_batch->ed->next); 164 164 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) { 165 size_t i = 0; 166 for (; i < ohci_batch->td_count; ++i) { 180 167 assert(ohci_batch->tds[i] != NULL); 181 168 usb_log_debug("TD %zu: %08x:%08x:%08x:%08x.\n", i, 182 169 ohci_batch->tds[i]->status, ohci_batch->tds[i]->cbp, 183 170 ohci_batch->tds[i]->next, ohci_batch->tds[i]->be); 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 171 if (!td_is_finished(ohci_batch->tds[i])) { 172 return false; 173 } 199 174 ohci_batch->usb_batch->error = td_error(ohci_batch->tds[i]); 200 175 if (ohci_batch->usb_batch->error != EOK) { … … 202 177 ohci_batch->usb_batch, i, 203 178 ohci_batch->tds[i]->status); 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; 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; 227 184 break; 228 185 } 229 186 } 230 assert(ohci_batch->usb_batch->transfered_size <= 231 ohci_batch->usb_batch->buffer_size);232 233 /* Store the remaining TD */ 187 188 assert(i <= ohci_batch->td_count); 189 ohci_batch->leave_td = i; 190 234 191 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep); 235 192 assert(ohci_ep); 236 193 ohci_ep->td = ohci_batch->tds[ohci_batch->leave_td]; 237 238 /* Make sure that we are leaving the right TD behind */ 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 */ 239 205 const uint32_t pa = addr_to_phys(ohci_ep->td); 240 206 assert(pa == (ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK)); … … 251 217 { 252 218 assert(ohci_batch); 253 ed_set_ tail_td(ohci_batch->ed, ohci_batch->tds[ohci_batch->td_count]);219 ed_set_end_td(ohci_batch->ed, ohci_batch->tds[ohci_batch->td_count]); 254 220 } 255 221 /*----------------------------------------------------------------------------*/ … … 281 247 const usb_direction_t status_dir = reverse_dir[dir]; 282 248 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);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]); 287 253 usb_log_debug("Created CONTROL SETUP TD: %08x:%08x:%08x:%08x.\n", 288 254 ohci_batch->tds[0]->status, ohci_batch->tds[0]->cbp, … … 290 256 buffer += ohci_batch->usb_batch->setup_size; 291 257 292 /* Data stage */258 /* data stage */ 293 259 size_t td_current = 1; 294 260 size_t remain_size = ohci_batch->usb_batch->buffer_size; … … 299 265 toggle = 1 - toggle; 300 266 301 td_init(ohci_batch->tds[td_current], 302 ohci_batch->tds[td_current + 1], 303 data_dir, buffer, transfer_size, toggle); 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]); 304 271 usb_log_debug("Created CONTROL DATA TD: %08x:%08x:%08x:%08x.\n", 305 272 ohci_batch->tds[td_current]->status, … … 314 281 } 315 282 316 /* Status stage */283 /* status stage */ 317 284 assert(td_current == ohci_batch->td_count - 1); 318 td_init(ohci_batch->tds[td_current], ohci_batch->tds[td_current + 1], 319 status_dir, NULL, 0, 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]); 320 288 usb_log_debug("Created CONTROL STATUS TD: %08x:%08x:%08x:%08x.\n", 321 289 ohci_batch->tds[td_current]->status, … … 355 323 ? OHCI_TD_MAX_TRANSFER : remain_size; 356 324 357 td_init( 358 ohci_batch->tds[td_current], ohci_batch->tds[td_current + 1], 359 dir, buffer, transfer_size, -1); 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]); 360 329 361 330 usb_log_debug("Created DATA TD: %08x:%08x:%08x:%08x.\n", -
uspace/drv/bus/usb/ohci/ohci_endpoint.c
r98fb010 r721d4b6e 102 102 } 103 103 104 ed_init(ohci_ep->ed, ep, ohci_ep->td); 104 ed_init(ohci_ep->ed, ep); 105 ed_set_td(ohci_ep->ed, ohci_ep->td); 105 106 endpoint_set_hc_data( 106 107 ep, ohci_ep, ohci_endpoint_fini, ohci_ep_toggle_get, ohci_ep_toggle_set); -
uspace/drv/bus/usb/ohci/root_hub.c
r98fb010 r721d4b6e 35 35 #include <errno.h> 36 36 #include <str_error.h> 37 #include <fibril_synch.h>38 37 39 38 #include <usb/debug.h> 40 #include <usb/dev/request.h>41 #include <usb/classes/hub.h>42 39 43 40 #include "root_hub.h" … … 46 43 #include <usb/dev/driver.h> 47 44 #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(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); 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); 119 117 static int control_request(rh_t *instance, usb_transfer_batch_t *request); 120 118 static inline void interrupt_request( … … 155 153 instance->unfinished_interrupt_transfer = NULL; 156 154 157 #if definedOHCI_POWER_SWITCH_no155 #ifdef OHCI_POWER_SWITCH_no 158 156 /* Set port power mode to no power-switching. (always on) */ 159 157 instance->registers->rh_desc_a |= RHDA_NPS_FLAG; 160 161 158 /* Set to no over-current reporting */ 162 159 instance->registers->rh_desc_a |= RHDA_NOCP_FLAG; 163 164 160 #elif defined OHCI_POWER_SWITCH_ganged 165 161 /* Set port power mode to no ganged power-switching. */ … … 167 163 instance->registers->rh_desc_a &= ~RHDA_PSM_FLAG; 168 164 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER; 169 170 165 /* Set to global over-current */ 171 166 instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG; … … 179 174 instance->registers->rh_desc_b &= (RHDB_PCC_MASK << RHDB_PCC_SHIFT); 180 175 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER; 181 182 176 /* Return control to per port state */ 183 177 instance->registers->rh_desc_b |= 184 178 ((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT; 185 186 179 /* Set per port over-current */ 187 180 instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG; … … 189 182 #endif 190 183 191 fibril_mutex_initialize(&instance->guard);192 184 rh_init_descriptors(instance); 193 185 … … 217 209 case USB_TRANSFER_INTERRUPT: 218 210 usb_log_debug("Root hub got INTERRUPT packet\n"); 219 fibril_mutex_lock(&instance->guard);220 assert(instance->unfinished_interrupt_transfer == NULL);221 211 const uint16_t mask = create_interrupt_mask(instance); 222 212 if (mask == 0) { 223 213 usb_log_debug("No changes..\n"); 214 assert(instance->unfinished_interrupt_transfer == NULL); 224 215 instance->unfinished_interrupt_transfer = request; 225 fibril_mutex_unlock(&instance->guard);226 216 return; 227 217 } 228 218 usb_log_debug("Processing changes...\n"); 229 219 interrupt_request(request, mask, instance->interrupt_mask_size); 230 fibril_mutex_unlock(&instance->guard);231 220 break; 232 221 … … 248 237 assert(instance); 249 238 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); 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; 261 249 } 262 250 /*----------------------------------------------------------------------------*/ … … 354 342 * @return Mask of changes. 355 343 */ 356 uint16_t create_interrupt_mask( constrh_t *instance)344 uint16_t create_interrupt_mask(rh_t *instance) 357 345 { 358 346 assert(instance); … … 384 372 * @return error code 385 373 */ 386 int get_status( constrh_t *instance, usb_transfer_batch_t *request)374 int get_status(rh_t *instance, usb_transfer_batch_t *request) 387 375 { 388 376 assert(instance); … … 430 418 * @return Error code 431 419 */ 432 int get_descriptor( constrh_t *instance, usb_transfer_batch_t *request)420 int get_descriptor(rh_t *instance, usb_transfer_batch_t *request) 433 421 { 434 422 assert(instance); … … 508 496 * @return error code 509 497 */ 510 int set_feature_port( constrh_t *instance, uint16_t feature, uint16_t port)498 int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port) 511 499 { 512 500 assert(instance); … … 547 535 * @return error code 548 536 */ 549 int clear_feature_port( constrh_t *instance, uint16_t feature, uint16_t port)537 int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port) 550 538 { 551 539 assert(instance); … … 604 592 * @return error code 605 593 */ 606 int set_feature( constrh_t *instance, usb_transfer_batch_t *request)594 int set_feature(rh_t *instance, usb_transfer_batch_t *request) 607 595 { 608 596 assert(instance); … … 640 628 * @return error code 641 629 */ 642 int clear_feature( constrh_t *instance, usb_transfer_batch_t *request)630 int clear_feature(rh_t *instance, usb_transfer_batch_t *request) 643 631 { 644 632 assert(instance); … … 647 635 const usb_device_request_setup_packet_t *setup_request = 648 636 (usb_device_request_setup_packet_t *) request->setup_buffer; 649 650 637 request->transfered_size = 0; 651 652 638 switch (setup_request->request_type) 653 639 { … … 661 647 /* 662 648 * Chapter 11.16.2 specifies that only C_HUB_LOCAL_POWER and 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 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 666 651 * as root hubs do not support local power status feature. 667 652 * (OHCI pg. 127) */ … … 735 720 "additional data\n"); 736 721 return clear_feature(instance, request); 737 738 722 case USB_DEVREQ_SET_FEATURE: 739 723 usb_log_debug2("Processing request without " -
uspace/drv/bus/usb/ohci/root_hub.h
r98fb010 r721d4b6e 47 47 */ 48 48 typedef struct rh { 49 fibril_mutex_t guard;50 49 /** pointer to ohci driver registers */ 51 50 ohci_regs_t *registers; -
uspace/drv/bus/usb/ohci/utils/malloc32.h
r98fb010 r721d4b6e 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 3248 49 43 /** Get physical address translation 50 44 * … … 68 62 */ 69 63 static inline void * malloc32(size_t size) 70 { return memalign( OHCI_ALIGN, size); }64 { return memalign(size, size); } 71 65 /*----------------------------------------------------------------------------*/ 72 66 /** Physical mallocator simulator
Note:
See TracChangeset
for help on using the changeset viewer.