Changes in uspace/drv/bus/usb/xhci/transfers.c [3038d51:e454d9c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/transfers.c
r3038d51 re454d9c 126 126 } 127 127 128 static int calculate_trb_count(xhci_transfer_t *transfer)129 {130 const size_t size = transfer->batch.buffer_size;131 return (size + PAGE_SIZE - 1 )/ PAGE_SIZE;132 }133 134 static void trb_set_buffer(xhci_transfer_t *transfer, xhci_trb_t *trb,135 size_t i, size_t total, size_t *remaining)136 {137 const uintptr_t ptr = dma_buffer_phys(&transfer->hc_buffer,138 transfer->hc_buffer.virt + i * PAGE_SIZE);139 140 trb->parameter = host2xhci(64, ptr);141 TRB_CTRL_SET_TD_SIZE(*trb, max(31, total - i - 1));142 if (*remaining > PAGE_SIZE) {143 TRB_CTRL_SET_XFER_LEN(*trb, PAGE_SIZE);144 *remaining -= PAGE_SIZE;145 }146 else {147 TRB_CTRL_SET_XFER_LEN(*trb, *remaining);148 *remaining = 0;149 }150 }151 152 128 static int schedule_control(xhci_hc_t* hc, xhci_transfer_t* transfer) 153 129 { … … 157 133 usb_device_request_setup_packet_t* setup = &batch->setup.packet; 158 134 159 size_t buffer_count = 0; 160 if (setup->length > 0) { 161 buffer_count = calculate_trb_count(transfer); 162 } 163 164 xhci_trb_t trbs[buffer_count + 2]; 165 166 xhci_trb_t *trb_setup = trbs; 135 xhci_trb_t trbs[3]; 136 int trbs_used = 0; 137 138 xhci_trb_t *trb_setup = trbs + trbs_used++; 167 139 xhci_trb_clean(trb_setup); 168 140 … … 183 155 184 156 /* Data stage */ 157 xhci_trb_t *trb_data = NULL; 185 158 if (setup->length > 0) { 159 trb_data = trbs + trbs_used++; 160 xhci_trb_clean(trb_data); 161 162 trb_data->parameter = host2xhci(64, transfer->hc_buffer.phys); 163 164 // data size (sent for OUT, or buffer size) 165 TRB_CTRL_SET_XFER_LEN(*trb_data, batch->buffer_size); 166 // FIXME: TD size 4.11.2.4 167 TRB_CTRL_SET_TD_SIZE(*trb_data, 1); 168 169 // Some more fields here, no idea what they mean 170 TRB_CTRL_SET_TRB_TYPE(*trb_data, XHCI_TRB_TYPE_DATA_STAGE); 171 186 172 int stage_dir = REQUEST_TYPE_IS_DEVICE_TO_HOST(setup->request_type) 187 173 ? STAGE_IN : STAGE_OUT; 188 size_t remaining = transfer->batch.buffer_size; 189 190 for (size_t i = 0; i < buffer_count; ++i) { 191 xhci_trb_clean(&trbs[i + 1]); 192 trb_set_buffer(transfer, &trbs[i + 1], i, buffer_count, &remaining); 193 194 TRB_CTRL_SET_DIR(trbs[i + 1], stage_dir); 195 TRB_CTRL_SET_TRB_TYPE(trbs[i + 1], XHCI_TRB_TYPE_DATA_STAGE); 196 197 if (i == buffer_count - 1) break; 198 199 /* Set the chain bit as this is not the last TRB */ 200 TRB_CTRL_SET_CHAIN(trbs[i], 1); 201 } 174 TRB_CTRL_SET_DIR(*trb_data, stage_dir); 202 175 } 203 176 204 177 /* Status stage */ 205 xhci_trb_t *trb_status = trbs + buffer_count + 1;178 xhci_trb_t *trb_status = trbs + trbs_used++; 206 179 xhci_trb_clean(trb_status); 207 180 … … 219 192 220 193 return xhci_trb_ring_enqueue_multiple(get_ring(transfer), trbs, 221 buffer_count + 2, &transfer->interrupt_trb_phys);194 trbs_used, &transfer->interrupt_trb_phys); 222 195 } 223 196 224 197 static int schedule_bulk(xhci_hc_t* hc, xhci_transfer_t *transfer) 225 198 { 199 xhci_trb_t trb; 200 xhci_trb_clean(&trb); 201 trb.parameter = host2xhci(64, transfer->hc_buffer.phys); 202 203 // data size (sent for OUT, or buffer size) 204 TRB_CTRL_SET_XFER_LEN(trb, transfer->batch.buffer_size); 205 226 206 /* The stream-enabled endpoints need to chain ED trb */ 227 207 xhci_endpoint_t *ep = xhci_endpoint_get(transfer->batch.ep); 228 208 if (!ep->primary_stream_data_size) { 229 const size_t buffer_count = calculate_trb_count(transfer); 230 xhci_trb_t trbs[buffer_count]; 231 size_t remaining = transfer->batch.buffer_size; 232 233 for (size_t i = 0; i < buffer_count; ++i) { 234 xhci_trb_clean(&trbs[i]); 235 trb_set_buffer(transfer, &trbs[i], i, buffer_count, &remaining); 236 TRB_CTRL_SET_TRB_TYPE(trbs[i], XHCI_TRB_TYPE_NORMAL); 237 238 if (i == buffer_count - 1) break; 239 240 /* Set the chain bit as this is not the last TRB */ 241 TRB_CTRL_SET_CHAIN(trbs[i], 1); 242 } 243 /* Set the interrupt bit for last TRB */ 244 TRB_CTRL_SET_IOC(trbs[buffer_count - 1], 1); 209 // FIXME: TD size 4.11.2.4 210 TRB_CTRL_SET_TD_SIZE(trb, 1); 211 212 // we want an interrupt after this td is done 213 TRB_CTRL_SET_IOC(trb, 1); 214 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL); 245 215 246 216 xhci_trb_ring_t* ring = get_ring(transfer); 247 return xhci_trb_ring_enqueue_multiple(ring, &trbs[0], buffer_count, 248 &transfer->interrupt_trb_phys); 217 return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys); 249 218 } 250 219 else { 220 TRB_CTRL_SET_TD_SIZE(trb, 2); 221 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL); 222 TRB_CTRL_SET_CHAIN(trb, 1); 223 TRB_CTRL_SET_ENT(trb, 1); 224 251 225 xhci_trb_ring_t* ring = get_ring(transfer); 252 226 if (!ring) { … … 254 228 } 255 229 256 const size_t buffer_count = calculate_trb_count(transfer); 257 xhci_trb_t trbs[buffer_count + 1]; 258 size_t remaining = transfer->batch.buffer_size; 259 260 for (size_t i = 0; i < buffer_count; ++i) { 261 xhci_trb_clean(&trbs[i]); 262 trb_set_buffer(transfer, &trbs[i], i, buffer_count + 1, &remaining); 263 TRB_CTRL_SET_TRB_TYPE(trbs[i], XHCI_TRB_TYPE_NORMAL); 264 TRB_CTRL_SET_CHAIN(trbs[i], 1); 230 int err = xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys); 231 232 if (err) { 233 return err; 265 234 } 266 TRB_CTRL_SET_ENT(trbs[buffer_count - 1], 1); 267 268 xhci_trb_clean(&trbs[buffer_count]); 269 trbs[buffer_count].parameter = host2xhci(64, (uintptr_t) transfer); 270 TRB_CTRL_SET_TRB_TYPE(trbs[buffer_count], XHCI_TRB_TYPE_EVENT_DATA); 271 TRB_CTRL_SET_IOC(trbs[buffer_count], 1); 272 273 return xhci_trb_ring_enqueue_multiple(ring, &trbs[0], buffer_count + 1, 274 &transfer->interrupt_trb_phys); 235 236 xhci_trb_clean(&trb); 237 trb.parameter = host2xhci(64, (uintptr_t) transfer); 238 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_EVENT_DATA); 239 TRB_CTRL_SET_IOC(trb, 1); 240 241 return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys); 275 242 } 276 243 } … … 278 245 static int schedule_interrupt(xhci_hc_t* hc, xhci_transfer_t* transfer) 279 246 { 280 const size_t buffer_count = calculate_trb_count(transfer); 281 xhci_trb_t trbs[buffer_count]; 282 size_t remaining = transfer->batch.buffer_size; 283 284 for (size_t i = 0; i < buffer_count; ++i) { 285 xhci_trb_clean(&trbs[i]); 286 trb_set_buffer(transfer, &trbs[i], i, buffer_count, &remaining); 287 TRB_CTRL_SET_TRB_TYPE(trbs[i], XHCI_TRB_TYPE_NORMAL); 288 289 if (i == buffer_count - 1) break; 290 291 /* Set the chain bit as this is not the last TRB */ 292 TRB_CTRL_SET_CHAIN(trbs[i], 1); 293 } 294 /* Set the interrupt bit for last TRB */ 295 TRB_CTRL_SET_IOC(trbs[buffer_count - 1], 1); 247 xhci_trb_t trb; 248 xhci_trb_clean(&trb); 249 trb.parameter = host2xhci(64, transfer->hc_buffer.phys); 250 251 // data size (sent for OUT, or buffer size) 252 TRB_CTRL_SET_XFER_LEN(trb, transfer->batch.buffer_size); 253 // FIXME: TD size 4.11.2.4 254 TRB_CTRL_SET_TD_SIZE(trb, 1); 255 256 // we want an interrupt after this td is done 257 TRB_CTRL_SET_IOC(trb, 1); 258 259 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL); 296 260 297 261 xhci_trb_ring_t* ring = get_ring(transfer); 298 return xhci_trb_ring_enqueue_multiple(ring, &trbs[0], buffer_count, 299 262 263 return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys); 300 264 } 301 265
Note:
See TracChangeset
for help on using the changeset viewer.