121
123
usb_transfer_batch_t *request, uint16_t mask, size_t size)
126
usb_log_debug("Sending interrupt vector(%zu) %hhx:%hhx.\n",
127
size, ((uint8_t*)&mask)[0], ((uint8_t*)&mask)[1]);
124
128
usb_transfer_batch_finish_error(request, &mask, size, EOK);
125
129
usb_transfer_batch_destroy(request);
151
155
instance->registers = regs;
152
instance->port_count =
153
(instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
156
instance->port_count = OHCI_RD(regs->rh_desc_a) & RHDA_NDS_MASK;
157
usb_log_debug2("rh_desc_a: %x.\n", OHCI_RD(regs->rh_desc_a));
154
158
if (instance->port_count > 15) {
155
159
usb_log_warning("OHCI specification does not allow more than 15"
156
160
" ports. Max 15 ports will be used");
162
166
instance->unfinished_interrupt_transfer = NULL;
164
168
#if defined OHCI_POWER_SWITCH_no
169
usb_log_debug("OHCI rh: Set power mode to no power switching.\n");
165
170
/* Set port power mode to no power-switching. (always on) */
166
instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
171
OHCI_SET(regs->rh_desc_a, RHDA_NPS_FLAG);
168
173
/* Set to no over-current reporting */
169
instance->registers->rh_desc_a |= RHDA_NOCP_FLAG;
174
OHCI_SET(regs->rh_desc_a, RHDA_NOCP_FLAG);
171
176
#elif defined OHCI_POWER_SWITCH_ganged
172
/* Set port power mode to no ganged power-switching. */
173
instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG;
174
instance->registers->rh_desc_a &= ~RHDA_PSM_FLAG;
175
instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
177
usb_log_debug("OHCI rh: Set power mode to ganged power switching.\n");
178
/* Set port power mode to ganged power-switching. */
179
OHCI_CLR(regs->rh_desc_a, RHDA_NPS_FLAG);
180
OHCI_CLR(regs->rh_desc_a, RHDA_PSM_FLAG);
182
/* Turn off power (hub driver will turn this back on)*/
183
OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER);
177
185
/* Set to global over-current */
178
instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
179
instance->registers->rh_desc_a &= ~RHDA_OCPM_FLAG;
186
OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG);
187
OHCI_CLR(regs->rh_desc_a, RHDA_OCPM_FLAG);
181
/* Set port power mode to no per port power-switching. */
182
instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG;
183
instance->registers->rh_desc_a |= RHDA_PSM_FLAG;
189
usb_log_debug("OHCI rh: Set power mode to per-port power switching.\n");
190
/* Set port power mode to per port power-switching. */
191
OHCI_CLR(regs->rh_desc_a, RHDA_NPS_FLAG);
192
OHCI_SET(regs->rh_desc_a, RHDA_PSM_FLAG);
185
194
/* Control all ports by global switch and turn them off */
186
instance->registers->rh_desc_b &= (RHDB_PCC_MASK << RHDB_PCC_SHIFT);
187
instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
195
OHCI_CLR(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT);
196
OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER);
189
198
/* Return control to per port state */
190
instance->registers->rh_desc_b |=
191
((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT;
199
OHCI_SET(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT);
193
201
/* Set per port over-current */
194
instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
195
instance->registers->rh_desc_a |= RHDA_OCPM_FLAG;
202
OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG);
203
OHCI_SET(regs->rh_desc_a, RHDA_OCPM_FLAG);
198
206
fibril_mutex_initialize(&instance->guard);
225
233
usb_log_debug("Root hub got INTERRUPT packet\n");
226
234
fibril_mutex_lock(&instance->guard);
227
235
assert(instance->unfinished_interrupt_transfer == NULL);
228
uint16_t mask = create_interrupt_mask(instance);
236
const uint16_t mask = create_interrupt_mask(instance);
230
usb_log_debug("No changes...\n");
238
usb_log_debug("No changes(%hx)...\n", mask);
231
239
instance->unfinished_interrupt_transfer = request;
233
241
usb_log_debug("Processing changes...\n");
256
264
fibril_mutex_lock(&instance->guard);
257
265
if (instance->unfinished_interrupt_transfer) {
258
266
usb_log_debug("Finalizing interrupt transfer\n");
259
uint16_t mask = create_interrupt_mask(instance);
267
const uint16_t mask = create_interrupt_mask(instance);
260
268
interrupt_request(instance->unfinished_interrupt_transfer,
261
269
mask, instance->interrupt_mask_size);
262
270
instance->unfinished_interrupt_transfer = NULL;
264
272
fibril_mutex_unlock(&instance->guard);
266
/*----------------------------------------------------------------------------*/
268
276
* Create hub descriptor.
305
313
instance->descriptors.hub[4] = 0;
306
314
/* bPwrOn2PwrGood */
307
instance->descriptors.hub[5] =
308
(hub_desc >> RHDA_POTPGT_SHIFT) & RHDA_POTPGT_MASK;
315
instance->descriptors.hub[5] = hub_desc >> RHDA_POTPGT_SHIFT;
309
316
/* bHubContrCurrent, root hubs don't need no power. */
310
317
instance->descriptors.hub[6] = 0;
312
319
/* Device Removable and some legacy 1.0 stuff*/
313
instance->descriptors.hub[7] =
314
(port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK & 0xff;
320
instance->descriptors.hub[7] = (port_desc >> RHDB_DR_SHIFT) & 0xff;
315
321
instance->descriptors.hub[8] = 0xff;
316
322
if (instance->interrupt_mask_size == 2) {
317
323
instance->descriptors.hub[8] =
318
(port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK >> 8;
324
(port_desc >> RHDB_DR_SHIFT) >> 8;
319
325
instance->descriptors.hub[9] = 0xff;
320
326
instance->descriptors.hub[10] = 0xff;
323
/*----------------------------------------------------------------------------*/
324
330
/** Initialize hub descriptors.
326
332
* A full configuration descriptor is assembled. The configuration and endpoint
340
346
instance->descriptors.endpoint.max_packet_size =
341
347
instance->interrupt_mask_size;
343
instance->descriptors.configuration.total_length =
349
instance->descriptors.configuration.total_length = uint16_host2usb(
344
350
sizeof(usb_standard_configuration_descriptor_t) +
345
351
sizeof(usb_standard_endpoint_descriptor_t) +
346
352
sizeof(usb_standard_interface_descriptor_t) +
347
instance->hub_descriptor_size;
353
instance->hub_descriptor_size);
349
/*----------------------------------------------------------------------------*/
351
357
* Create bitmap of changes to answer status interrupt.
363
369
uint16_t mask = 0;
365
371
/* Only local power source change and over-current change can happen */
366
if (instance->registers->rh_status & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
372
if (OHCI_RD(instance->registers->rh_status)
373
& (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
369
376
for (size_t port = 1; port <= instance->port_count; ++port) {
370
377
/* Write-clean bits are those that indicate change */
371
if (RHPS_CHANGE_WC_MASK
372
& instance->registers->rh_port_status[port - 1]) {
378
if (OHCI_RD(instance->registers->rh_port_status[port - 1])
379
& RHPS_CHANGE_WC_MASK) {
374
380
mask |= (1 << port);
377
/* USB is little endian */
378
return host2uint32_t_le(mask);
383
usb_log_debug2("OHCI root hub interrupt mask: %hx.\n", mask);
384
return uint16_host2usb(mask);
380
/*----------------------------------------------------------------------------*/
382
388
* Create answer to status request.
405
413
"status request.\n", request->buffer_size);
406
414
TRANSFER_END(request, EOVERFLOW);
408
uint32_t data = instance->registers->rh_status &
409
(RHS_LPS_FLAG | RHS_LPSC_FLAG
410
| RHS_OCI_FLAG | RHS_OCIC_FLAG);
416
const uint32_t data =
417
OHCI_RD(instance->registers->rh_status) &
418
(RHS_LPS_FLAG | RHS_LPSC_FLAG
419
| RHS_OCI_FLAG | RHS_OCIC_FLAG);
411
420
TRANSFER_END_DATA(request, &data, sizeof(data));
419
428
"status request.\n", request->buffer_size);
420
429
TRANSFER_END(request, EOVERFLOW);
422
unsigned port = request_packet->index;
431
const unsigned port = index;
423
432
if (port < 1 || port > instance->port_count)
424
433
TRANSFER_END(request, EINVAL);
427
instance->registers->rh_port_status[port - 1];
434
/* Register format matches the format of port status
436
const uint32_t data = uint32_host2usb(OHCI_RD(
437
instance->registers->rh_port_status[port - 1]));
428
438
TRANSFER_END_DATA(request, &data, sizeof(data));
430
440
case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE):
433
443
"get status request.\n", request->buffer_size);
434
444
TRANSFER_END(request, EOVERFLOW);
446
const uint16_t data =
437
447
uint16_host2usb(USB_DEVICE_STATUS_SELF_POWERED);
438
448
TRANSFER_END_DATA(request, &data, sizeof(data));
441
451
case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE):
442
452
/* Hubs are allowed to have only one interface */
443
if (request_packet->index != 0)
444
454
TRANSFER_END(request, EINVAL);
445
455
/* Fall through, as the answer will be the same: 0x0000 */
446
456
case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT):
447
457
/* Endpoint 0 (default control) and 1 (interrupt) */
448
if (request_packet->index >= 2)
449
459
TRANSFER_END(request, EINVAL);
451
461
if (request->buffer_size < 2) {
482
492
usb_device_request_setup_packet_t *setup_request =
483
493
(usb_device_request_setup_packet_t *) request->setup_buffer;
484
uint16_t setup_request_value = setup_request->value_high;
485
switch (setup_request_value)
494
/* "The wValue field specifies the descriptor type in the high byte
495
* and the descriptor index in the low byte (refer to Table 9-5)." */
496
const int desc_type = uint16_usb2host(setup_request->value) >> 8;
487
499
case USB_DESCTYPE_HUB:
488
500
usb_log_debug2("USB_DESCTYPE_HUB\n");
529
541
"%d\n\tindex %d\n\tlen %d\n ",
530
542
setup_request->value,
531
543
setup_request->request_type, setup_request->request,
532
setup_request_value, setup_request->index,
544
desc_type, setup_request->index,
533
545
setup_request->length);
534
546
TRANSFER_END(request, EINVAL);
537
549
TRANSFER_END(request, ENOTSUP);
539
/*----------------------------------------------------------------------------*/
541
553
* process feature-enabling request on hub
553
565
if (port < 1 || port > instance->port_count)
558
case USB_HUB_FEATURE_PORT_POWER: //8
559
/* No power switching */
560
if (instance->registers->rh_desc_a & RHDA_NPS_FLAG)
562
/* Ganged power switching */
563
if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) {
564
instance->registers->rh_status = RHS_SET_GLOBAL_POWER;
569
case USB_HUB_FEATURE_PORT_POWER: /*8*/
571
const uint32_t rhda =
572
OHCI_RD(instance->registers->rh_desc_a);
573
/* No power switching */
574
if (rhda & RHDA_NPS_FLAG)
576
/* Ganged power switching, one port powers all */
577
if (!(rhda & RHDA_PSM_FLAG)) {
578
OHCI_WR(instance->registers->rh_status,
579
RHS_SET_GLOBAL_POWER);
567
case USB_HUB_FEATURE_PORT_ENABLE: //1
568
case USB_HUB_FEATURE_PORT_SUSPEND: //2
569
case USB_HUB_FEATURE_PORT_RESET: //4
570
/* Nice thing is that these shifts correspond to the position
571
* of control bits in register */
572
instance->registers->rh_port_status[port - 1] = (1 << feature);
584
case USB_HUB_FEATURE_PORT_ENABLE: /*1*/
585
case USB_HUB_FEATURE_PORT_SUSPEND: /*2*/
586
case USB_HUB_FEATURE_PORT_RESET: /*4*/
587
usb_log_debug2("Setting port POWER, ENABLE, SUSPEND or RESET "
588
"on port %"PRIu16".\n", port);
589
OHCI_WR(instance->registers->rh_port_status[port - 1],
578
/*----------------------------------------------------------------------------*/
580
598
* Process feature clear request.
595
613
/* Enabled features to clear: see page 269 of USB specs */
598
case USB_HUB_FEATURE_PORT_POWER: //8
599
/* No power switching */
600
if (instance->registers->rh_desc_a & RHDA_NPS_FLAG)
602
/* Ganged power switching */
603
if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) {
604
instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
616
case USB_HUB_FEATURE_PORT_POWER: /*8*/
618
const uint32_t rhda =
619
OHCI_RD(instance->registers->rh_desc_a);
620
/* No power switching */
621
if (rhda & RHDA_NPS_FLAG)
623
/* Ganged power switching, one port powers all */
624
if (!(rhda & RHDA_PSM_FLAG)) {
625
OHCI_WR(instance->registers->rh_status,
626
RHS_CLEAR_GLOBAL_POWER);
629
OHCI_WR(instance->registers->rh_port_status[port - 1],
630
RHPS_CLEAR_PORT_POWER);
607
instance->registers->rh_port_status[port - 1] =
608
RHPS_CLEAR_PORT_POWER;
611
case USB_HUB_FEATURE_PORT_ENABLE: //1
612
instance->registers->rh_port_status[port - 1] =
613
RHPS_CLEAR_PORT_ENABLE;
616
case USB_HUB_FEATURE_PORT_SUSPEND: //2
617
instance->registers->rh_port_status[port - 1] =
618
RHPS_CLEAR_PORT_SUSPEND;
621
case USB_HUB_FEATURE_C_PORT_CONNECTION: //16
622
case USB_HUB_FEATURE_C_PORT_ENABLE: //17
623
case USB_HUB_FEATURE_C_PORT_SUSPEND: //18
624
case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: //19
625
case USB_HUB_FEATURE_C_PORT_RESET: //20
626
/* Nice thing is that these shifts correspond to the position
627
* of control bits in register */
628
instance->registers->rh_port_status[port - 1] = (1 << feature);
634
case USB_HUB_FEATURE_PORT_ENABLE: /*1*/
635
OHCI_WR(instance->registers->rh_port_status[port - 1],
636
RHPS_CLEAR_PORT_ENABLE);
639
case USB_HUB_FEATURE_PORT_SUSPEND: /*2*/
640
OHCI_WR(instance->registers->rh_port_status[port - 1],
641
RHPS_CLEAR_PORT_SUSPEND);
644
case USB_HUB_FEATURE_C_PORT_CONNECTION: /*16*/
645
case USB_HUB_FEATURE_C_PORT_ENABLE: /*17*/
646
case USB_HUB_FEATURE_C_PORT_SUSPEND: /*18*/
647
case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: /*19*/
648
case USB_HUB_FEATURE_C_PORT_RESET: /*20*/
649
usb_log_debug2("Clearing port C_CONNECTION, C_ENABLE, "
650
"C_SUSPEND, C_OC or C_RESET on port %"PRIu16".\n", port);
651
/* Bit offsets correspond to the feature number */
652
OHCI_WR(instance->registers->rh_port_status[port - 1],
635
/*----------------------------------------------------------------------------*/
637
662
* process one of requests that do not request nor carry additional data
654
679
case USB_HUB_REQ_TYPE_SET_PORT_FEATURE:
655
680
usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
656
int ret = set_feature_port(instance,
681
const int ret = set_feature_port(instance,
657
682
setup_request->value, setup_request->index);
658
683
TRANSFER_END(request, ret);
693
718
case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE:
694
719
usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n");
695
int ret = clear_feature_port(instance,
720
const int ret = clear_feature_port(instance,
696
721
setup_request->value, setup_request->index);
697
722
TRANSFER_END(request, ret);
705
730
* C_HUB_LOCAL_POWER is not supported
706
731
* as root hubs do not support local power status feature.
707
732
* (OHCI pg. 127) */
708
if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
709
instance->registers->rh_status = RHS_OCIC_FLAG;
733
if (uint16_usb2host(setup_request->value)
734
== USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
735
OHCI_WR(instance->registers->rh_status, RHS_OCIC_FLAG);
710
736
TRANSFER_END(request, EOK);
712
738
//TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL
789
815
if (uint16_usb2host(setup_request->value) > 127)
790
816
TRANSFER_END(request, EINVAL);
792
instance->address = setup_request->value;
818
instance->address = uint16_usb2host(setup_request->value);
793
819
TRANSFER_END(request, EOK);
795
821
case USB_DEVREQ_SET_CONFIGURATION:
796
822
usb_log_debug("USB_DEVREQ_SET_CONFIGURATION: %u\n",
797
setup_request->value);
823
uint16_usb2host(setup_request->value));
798
824
/* We have only one configuration, it's number is 1 */
799
825
if (uint16_usb2host(setup_request->value) != 1)
800
826
TRANSFER_END(request, EINVAL);