2 * PROJECT: ReactOS USB OHCI Miniport Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: USBOHCI main driver functions
5 * COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru>
13 #define NDEBUG_OHCI_TRACE
16 USBPORT_REGISTRATION_PACKET RegPacket
;
18 static const UCHAR Index
[8] =
20 ENDPOINT_INTERRUPT_1ms
- 1,
21 ENDPOINT_INTERRUPT_2ms
- 1,
22 ENDPOINT_INTERRUPT_4ms
- 1,
23 ENDPOINT_INTERRUPT_8ms
- 1,
24 ENDPOINT_INTERRUPT_16ms
- 1,
25 ENDPOINT_INTERRUPT_32ms
- 1,
26 ENDPOINT_INTERRUPT_32ms
- 1,
27 ENDPOINT_INTERRUPT_32ms
- 1
30 static const UCHAR Balance
[OHCI_NUMBER_OF_INTERRUPTS
] =
32 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30,
33 1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31
38 OHCI_DumpHcdED(POHCI_HCD_ED ED
)
40 DPRINT("ED - %p\n", ED
);
41 DPRINT("EndpointControl - %X\n", ED
->HwED
.EndpointControl
.AsULONG
);
42 DPRINT("TailPointer - %08X\n", ED
->HwED
.TailPointer
);
43 DPRINT("HeadPointer - %08X\n", ED
->HwED
.HeadPointer
);
44 DPRINT("NextED - %08X\n", ED
->HwED
.NextED
);
49 OHCI_DumpHcdTD(POHCI_HCD_TD TD
)
51 DPRINT("TD - %p\n", TD
);
52 DPRINT("gTD.Control - %08X\n", TD
->HwTD
.gTD
.Control
.AsULONG
);
53 if (TD
->HwTD
.gTD
.CurrentBuffer
)
54 DPRINT("gTD.CurrentBuffer - %08X\n", TD
->HwTD
.gTD
.CurrentBuffer
);
55 if (TD
->HwTD
.gTD
.NextTD
)
56 DPRINT("gTD.NextTD - %08X\n", TD
->HwTD
.gTD
.NextTD
);
57 if (TD
->HwTD
.gTD
.BufferEnd
)
58 DPRINT("gTD.BufferEnd - %08X\n", TD
->HwTD
.gTD
.BufferEnd
);
60 if (TD
->HwTD
.SetupPacket
.bmRequestType
.B
)
61 DPRINT("bmRequestType - %02X\n", TD
->HwTD
.SetupPacket
.bmRequestType
.B
);
62 if (TD
->HwTD
.SetupPacket
.bRequest
)
63 DPRINT("bRequest - %02X\n", TD
->HwTD
.SetupPacket
.bRequest
);
64 if (TD
->HwTD
.SetupPacket
.wValue
.W
)
65 DPRINT("wValue - %04X\n", TD
->HwTD
.SetupPacket
.wValue
.W
);
66 if (TD
->HwTD
.SetupPacket
.wIndex
.W
)
67 DPRINT("wIndex - %04X\n", TD
->HwTD
.SetupPacket
.wIndex
.W
);
68 if (TD
->HwTD
.SetupPacket
.wLength
)
69 DPRINT("wLength - %04X\n", TD
->HwTD
.SetupPacket
.wLength
);
71 DPRINT("PhysicalAddress - %p\n", TD
->PhysicalAddress
);
72 DPRINT("Flags - %X\n", TD
->Flags
);
73 DPRINT("OhciTransfer - %08X\n", TD
->OhciTransfer
);
74 DPRINT("NextHcdTD - %08X\n", TD
->NextHcdTD
);
76 DPRINT("TransferLen - %X\n", TD
->TransferLen
);
81 OHCI_EnableList(IN POHCI_EXTENSION OhciExtension
,
82 IN POHCI_ENDPOINT OhciEndpoint
)
84 POHCI_OPERATIONAL_REGISTERS OperationalRegs
;
85 PULONG CommandStatusReg
;
87 OHCI_REG_COMMAND_STATUS CommandStatus
;
89 DPRINT_OHCI("OHCI_EnableList: ... \n");
91 OperationalRegs
= OhciExtension
->OperationalRegs
;
92 CommandStatusReg
= (PULONG
)&OperationalRegs
->HcCommandStatus
;
94 CommandStatus
.AsULONG
= 0;
96 if (READ_REGISTER_ULONG((PULONG
)&OperationalRegs
->HcControlHeadED
))
97 CommandStatus
.ControlListFilled
= 1;
99 if (READ_REGISTER_ULONG((PULONG
)&OperationalRegs
->HcBulkHeadED
))
100 CommandStatus
.BulkListFilled
= 1;
102 TransferType
= OhciEndpoint
->EndpointProperties
.TransferType
;
104 if (TransferType
== USBPORT_TRANSFER_TYPE_BULK
)
105 CommandStatus
.BulkListFilled
= 1;
106 else if (TransferType
== USBPORT_TRANSFER_TYPE_CONTROL
)
107 CommandStatus
.ControlListFilled
= 1;
109 WRITE_REGISTER_ULONG(CommandStatusReg
, CommandStatus
.AsULONG
);
114 OHCI_InsertEndpointInSchedule(IN POHCI_ENDPOINT OhciEndpoint
)
116 POHCI_STATIC_ED HeadED
;
119 PLIST_ENTRY HeadLink
;
121 DPRINT_OHCI("OHCI_InsertEndpointInSchedule: OhciEndpoint - %p\n",
124 ED
= OhciEndpoint
->HcdED
;
126 HeadED
= OhciEndpoint
->HeadED
;
127 HeadLink
= &HeadED
->Link
;
129 if (IsListEmpty(HeadLink
))
131 InsertHeadList(HeadLink
, &ED
->HcdEDLink
);
133 if (HeadED
->Type
== OHCI_STATIC_ED_TYPE_CONTROL
||
134 HeadED
->Type
== OHCI_STATIC_ED_TYPE_BULK
)
136 ED
->HwED
.NextED
= READ_REGISTER_ULONG(HeadED
->pNextED
);
137 WRITE_REGISTER_ULONG(HeadED
->pNextED
, ED
->PhysicalAddress
);
139 else if (HeadED
->Type
== OHCI_STATIC_ED_TYPE_INTERRUPT
)
141 ED
->HwED
.NextED
= *HeadED
->pNextED
;
142 *HeadED
->pNextED
= ED
->PhysicalAddress
;
146 DPRINT1("OHCI_InsertEndpointInSchedule: Unknown HeadED->Type - %x\n",
153 PrevED
= CONTAINING_RECORD(HeadLink
->Blink
,
157 InsertTailList(HeadLink
, &ED
->HcdEDLink
);
160 PrevED
->HwED
.NextED
= ED
->PhysicalAddress
;
166 OHCI_InitializeED(IN POHCI_ENDPOINT OhciEndpoint
,
168 IN POHCI_HCD_TD FirstTD
,
171 OHCI_ENDPOINT_CONTROL EndpointControl
;
172 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
;
174 DPRINT_OHCI("OHCI_InitializeED: OhciEndpoint - %p, ED - %p, FirstTD - %p, EdPA - %p\n",
180 RtlZeroMemory(ED
, sizeof(OHCI_HCD_ED
));
182 ED
->PhysicalAddress
= EdPA
;
184 EndpointProperties
= &OhciEndpoint
->EndpointProperties
;
186 EndpointControl
= ED
->HwED
.EndpointControl
;
188 EndpointControl
.FunctionAddress
= EndpointProperties
->DeviceAddress
;
189 EndpointControl
.EndpointNumber
= EndpointProperties
->EndpointAddress
;
190 EndpointControl
.MaximumPacketSize
= EndpointProperties
->TotalMaxPacketSize
;
192 if (EndpointProperties
->TransferType
== USBPORT_TRANSFER_TYPE_CONTROL
)
194 EndpointControl
.Direction
= OHCI_ED_DATA_FLOW_DIRECTION_FROM_TD
;
196 else if (EndpointProperties
->Direction
)
198 EndpointControl
.Direction
= OHCI_ED_DATA_FLOW_DIRECTION_OUT
;
202 EndpointControl
.Direction
= OHCI_ED_DATA_FLOW_DIRECTION_IN
;
205 if (EndpointProperties
->DeviceSpeed
== UsbLowSpeed
)
206 EndpointControl
.Speed
= OHCI_ENDPOINT_LOW_SPEED
;
208 if (EndpointProperties
->TransferType
== USBPORT_TRANSFER_TYPE_ISOCHRONOUS
)
209 EndpointControl
.Format
= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT
;
211 EndpointControl
.sKip
= 1;
213 ED
->HwED
.EndpointControl
= EndpointControl
;
215 ED
->HwED
.TailPointer
= FirstTD
->PhysicalAddress
;
216 ED
->HwED
.HeadPointer
= FirstTD
->PhysicalAddress
;
218 FirstTD
->Flags
|= OHCI_HCD_TD_FLAG_ALLOCATED
;
220 OhciEndpoint
->HcdTailP
= FirstTD
;
221 OhciEndpoint
->HcdHeadP
= FirstTD
;
228 OHCI_InitializeTDs(IN POHCI_ENDPOINT OhciEndpoint
,
229 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
)
236 ASSERT(EndpointProperties
->BufferLength
> sizeof(OHCI_HCD_ED
));
238 TdCount
= (EndpointProperties
->BufferLength
- sizeof(OHCI_HCD_ED
)) /
241 OhciEndpoint
->MaxTransferDescriptors
= TdCount
;
243 DPRINT_OHCI("OHCI_InitializeTDs: TdCount - %x\n", TdCount
);
247 TdVA
= OhciEndpoint
->FirstTD
;
249 TdPA
= EndpointProperties
->BufferPA
+ sizeof(OHCI_HCD_ED
);
251 for (ix
= 0; ix
< TdCount
; ix
++)
253 DPRINT_OHCI("OHCI_InitializeTDs: TdVA - %p, TdPA - %08X\n", TdVA
, TdPA
);
255 RtlZeroMemory(TdVA
, sizeof(OHCI_HCD_TD
));
257 TdVA
->PhysicalAddress
= TdPA
;
259 TdVA
->OhciTransfer
= 0;
262 TdPA
+= sizeof(OHCI_HCD_TD
);
268 OHCI_OpenControlEndpoint(IN POHCI_EXTENSION OhciExtension
,
269 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
270 IN POHCI_ENDPOINT OhciEndpoint
)
274 DPRINT_OHCI("OHCI_OpenControlEndpoint: ... \n");
276 ED
= (POHCI_HCD_ED
)EndpointProperties
->BufferVA
;
278 OhciEndpoint
->FirstTD
= (POHCI_HCD_TD
)((ULONG_PTR
)ED
+ sizeof(OHCI_HCD_ED
));
279 OhciEndpoint
->HeadED
= &OhciExtension
->ControlStaticED
;
281 OHCI_InitializeTDs(OhciEndpoint
, EndpointProperties
);
283 OhciEndpoint
->HcdED
= OHCI_InitializeED(OhciEndpoint
,
285 OhciEndpoint
->FirstTD
,
286 EndpointProperties
->BufferPA
);
288 OhciEndpoint
->HcdED
->Flags
= OHCI_HCD_ED_FLAG_CONTROL
|
289 OHCI_HCD_ED_FLAG_RESET_ON_HALT
;
291 OHCI_InsertEndpointInSchedule(OhciEndpoint
);
293 return MP_STATUS_SUCCESS
;
298 OHCI_OpenBulkEndpoint(IN POHCI_EXTENSION OhciExtension
,
299 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
300 IN POHCI_ENDPOINT OhciEndpoint
)
304 DPRINT_OHCI("OHCI_OpenBulkEndpoint: ... \n");
306 ED
= (POHCI_HCD_ED
)EndpointProperties
->BufferVA
;
308 OhciEndpoint
->FirstTD
= (POHCI_HCD_TD
)((ULONG_PTR
)ED
+ sizeof(OHCI_HCD_ED
));
309 OhciEndpoint
->HeadED
= &OhciExtension
->BulkStaticED
;
311 OHCI_InitializeTDs(OhciEndpoint
, EndpointProperties
);
313 OhciEndpoint
->HcdED
= OHCI_InitializeED(OhciEndpoint
,
315 OhciEndpoint
->FirstTD
,
316 EndpointProperties
->BufferPA
);
318 OHCI_InsertEndpointInSchedule(OhciEndpoint
);
320 return MP_STATUS_SUCCESS
;
325 OHCI_OpenInterruptEndpoint(IN POHCI_EXTENSION OhciExtension
,
326 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
327 IN POHCI_ENDPOINT OhciEndpoint
)
332 ULONG ScheduleOffset
;
334 DPRINT_OHCI("OHCI_OpenInterruptEndpoint: ... \n");
336 ED
= (POHCI_HCD_ED
)EndpointProperties
->BufferVA
;
338 OhciEndpoint
->FirstTD
= (POHCI_HCD_TD
)((ULONG_PTR
)ED
+ sizeof(OHCI_HCD_ED
));
340 Period
= EndpointProperties
->Period
;
344 while (!(Period
& 1))
350 ASSERT(PeriodIdx
< ARRAYSIZE(Index
));
352 ScheduleOffset
= EndpointProperties
->ScheduleOffset
;
353 DPRINT_OHCI("OHCI_OpenInterruptEndpoint: InitTD. Index[PeriodIdx] - %x, ScheduleOffset - %x\n",
357 OhciEndpoint
->HeadED
= &OhciExtension
->IntStaticED
[Index
[PeriodIdx
] +
360 //OhciEndpoint->HeadED->UsbBandwidth += EndpointProperties->UsbBandwidth;
362 OHCI_InitializeTDs(OhciEndpoint
, EndpointProperties
);
364 OhciEndpoint
->HcdED
= OHCI_InitializeED(OhciEndpoint
,
366 OhciEndpoint
->FirstTD
,
367 EndpointProperties
->BufferPA
);
369 OHCI_InsertEndpointInSchedule(OhciEndpoint
);
371 return MP_STATUS_SUCCESS
;
376 OHCI_OpenIsoEndpoint(IN POHCI_EXTENSION OhciExtension
,
377 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
378 IN POHCI_ENDPOINT OhciEndpoint
)
380 DPRINT1("OHCI_OpenIsoEndpoint: UNIMPLEMENTED. FIXME\n");
381 return MP_STATUS_NOT_SUPPORTED
;
386 OHCI_OpenEndpoint(IN PVOID ohciExtension
,
387 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
388 IN PVOID ohciEndpoint
)
390 POHCI_EXTENSION OhciExtension
= ohciExtension
;
391 POHCI_ENDPOINT OhciEndpoint
= ohciEndpoint
;
395 DPRINT_OHCI("OHCI_OpenEndpoint: ... \n");
397 RtlCopyMemory(&OhciEndpoint
->EndpointProperties
,
399 sizeof(OhciEndpoint
->EndpointProperties
));
401 InitializeListHead(&OhciEndpoint
->TDList
);
403 TransferType
= EndpointProperties
->TransferType
;
405 switch (TransferType
)
407 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS
:
408 MPStatus
= OHCI_OpenIsoEndpoint(OhciExtension
,
413 case USBPORT_TRANSFER_TYPE_CONTROL
:
414 MPStatus
= OHCI_OpenControlEndpoint(OhciExtension
,
419 case USBPORT_TRANSFER_TYPE_BULK
:
420 MPStatus
= OHCI_OpenBulkEndpoint(OhciExtension
,
425 case USBPORT_TRANSFER_TYPE_INTERRUPT
:
426 MPStatus
= OHCI_OpenInterruptEndpoint(OhciExtension
,
432 MPStatus
= MP_STATUS_NOT_SUPPORTED
;
441 OHCI_ReopenEndpoint(IN PVOID ohciExtension
,
442 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
443 IN PVOID ohciEndpoint
)
445 POHCI_ENDPOINT OhciEndpoint
= ohciEndpoint
;
448 DPRINT_OHCI("OHCI_ReopenEndpoint: ... \n");
450 ED
= OhciEndpoint
->HcdED
;
452 RtlCopyMemory(&OhciEndpoint
->EndpointProperties
,
454 sizeof(OhciEndpoint
->EndpointProperties
));
456 ED
->HwED
.EndpointControl
.FunctionAddress
=
457 OhciEndpoint
->EndpointProperties
.DeviceAddress
;
459 ED
->HwED
.EndpointControl
.MaximumPacketSize
=
460 OhciEndpoint
->EndpointProperties
.TotalMaxPacketSize
;
462 return MP_STATUS_SUCCESS
;
467 OHCI_QueryEndpointRequirements(IN PVOID ohciExtension
,
468 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
469 IN PUSBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements
)
473 DPRINT_OHCI("OHCI_QueryEndpointRequirements: ... \n");
475 TransferType
= EndpointProperties
->TransferType
;
477 switch (TransferType
)
479 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS
:
480 DPRINT_OHCI("OHCI_QueryEndpointRequirements: IsoTransfer\n");
481 EndpointRequirements
->MaxTransferSize
= OHCI_MAX_ISO_TRANSFER_SIZE
;
482 EndpointRequirements
->HeaderBufferSize
=
483 sizeof(OHCI_HCD_ED
) + OHCI_MAX_ISO_TD_COUNT
* sizeof(OHCI_HCD_TD
);
486 case USBPORT_TRANSFER_TYPE_CONTROL
:
487 DPRINT_OHCI("OHCI_QueryEndpointRequirements: ControlTransfer\n");
488 EndpointRequirements
->MaxTransferSize
= OHCI_MAX_CONTROL_TRANSFER_SIZE
;
489 EndpointRequirements
->HeaderBufferSize
=
490 sizeof(OHCI_HCD_ED
) + OHCI_MAX_CONTROL_TD_COUNT
* sizeof(OHCI_HCD_TD
);
493 case USBPORT_TRANSFER_TYPE_BULK
:
494 DPRINT_OHCI("OHCI_QueryEndpointRequirements: BulkTransfer\n");
495 EndpointRequirements
->MaxTransferSize
= OHCI_MAX_BULK_TRANSFER_SIZE
;
496 EndpointRequirements
->HeaderBufferSize
=
497 sizeof(OHCI_HCD_ED
) + OHCI_MAX_BULK_TD_COUNT
* sizeof(OHCI_HCD_TD
);
500 case USBPORT_TRANSFER_TYPE_INTERRUPT
:
501 DPRINT_OHCI("OHCI_QueryEndpointRequirements: InterruptTransfer\n");
502 EndpointRequirements
->MaxTransferSize
= OHCI_MAX_INTERRUPT_TRANSFER_SIZE
;
503 EndpointRequirements
->HeaderBufferSize
=
504 sizeof(OHCI_HCD_ED
) + OHCI_MAX_INTERRUPT_TD_COUNT
* sizeof(OHCI_HCD_TD
);
508 DPRINT1("OHCI_QueryEndpointRequirements: Unknown TransferType - %x\n",
517 OHCI_CloseEndpoint(IN PVOID ohciExtension
,
518 IN PVOID ohciEndpoint
,
519 IN BOOLEAN IsDoDisablePeriodic
)
522 DPRINT1("OHCI_CloseEndpoint: Not supported\n");
529 OHCI_TakeControlHC(IN POHCI_EXTENSION OhciExtension
,
530 IN PUSBPORT_RESOURCES Resources
)
532 POHCI_OPERATIONAL_REGISTERS OperationalRegs
;
534 PULONG InterruptEnableReg
;
535 PULONG InterruptDisableReg
;
536 PULONG CommandStatusReg
;
537 PULONG InterruptStatusReg
;
538 OHCI_REG_CONTROL Control
;
539 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable
;
540 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable
;
541 OHCI_REG_COMMAND_STATUS CommandStatus
;
542 OHCI_REG_INTERRUPT_STATUS IntStatus
;
543 LARGE_INTEGER EndTime
;
544 LARGE_INTEGER SystemTime
;
546 DPRINT("OHCI_TakeControlHC: ...\n");
548 OperationalRegs
= OhciExtension
->OperationalRegs
;
550 ControlReg
= (PULONG
)&OperationalRegs
->HcControl
;
551 InterruptEnableReg
= (PULONG
)&OperationalRegs
->HcInterruptEnable
;
552 InterruptDisableReg
= (PULONG
)&OperationalRegs
->HcInterruptDisable
;
553 CommandStatusReg
= (PULONG
)&OperationalRegs
->HcCommandStatus
;
554 InterruptStatusReg
= (PULONG
)&OperationalRegs
->HcInterruptStatus
;
556 /* 5.1.1.3 Take Control of Host Controller */
557 Control
.AsULONG
= READ_REGISTER_ULONG(ControlReg
);
559 if (Control
.InterruptRouting
== 0)
560 return MP_STATUS_SUCCESS
;
562 DPRINT1("OHCI_TakeControlHC: detected Legacy BIOS\n");
564 IntEnable
.AsULONG
= READ_REGISTER_ULONG(InterruptEnableReg
);
566 DPRINT("OHCI_TakeControlHC: Control - %lX, IntEnable - %lX\n",
570 if (Control
.HostControllerFunctionalState
== OHCI_HC_STATE_RESET
&&
571 IntEnable
.AsULONG
== 0)
574 WRITE_REGISTER_ULONG(ControlReg
, Control
.AsULONG
);
575 return MP_STATUS_SUCCESS
;
578 /* Enable interrupt generations */
579 IntEnable
.AsULONG
= 0;
580 IntEnable
.MasterInterruptEnable
= 1;
582 WRITE_REGISTER_ULONG(InterruptEnableReg
, IntEnable
.AsULONG
);
584 /* Request a change of control of the HC */
585 CommandStatus
.AsULONG
= 0;
586 CommandStatus
.OwnershipChangeRequest
= 1;
588 WRITE_REGISTER_ULONG(CommandStatusReg
, CommandStatus
.AsULONG
);
590 /* Disable interrupt generation due to Root Hub Status Change */
591 IntDisable
.AsULONG
= 0;
592 IntDisable
.RootHubStatusChange
= 1;
594 WRITE_REGISTER_ULONG(InterruptDisableReg
, IntDisable
.AsULONG
);
596 /* Monitoring the InterruptRouting bit
597 to determine when the ownership change has taken effect. */
599 KeQuerySystemTime(&EndTime
);
600 EndTime
.QuadPart
+= 500 * 10000; // 0.5 sec;
604 Control
.AsULONG
= READ_REGISTER_ULONG(ControlReg
);
606 if (Control
.InterruptRouting
== 0)
608 /* Clear all bits in register */
609 IntStatus
.AsULONG
= 0xFFFFFFFF;
610 WRITE_REGISTER_ULONG(InterruptStatusReg
, IntStatus
.AsULONG
);
612 /* Disable interrupt generations */
613 IntDisable
.AsULONG
= 0;
614 IntDisable
.MasterInterruptEnable
= 1;
616 WRITE_REGISTER_ULONG(InterruptDisableReg
, IntDisable
.AsULONG
);
618 return MP_STATUS_SUCCESS
;
621 KeQuerySystemTime(&SystemTime
);
623 while (SystemTime
.QuadPart
< EndTime
.QuadPart
);
625 return MP_STATUS_HW_ERROR
;
630 OHCI_StartController(IN PVOID ohciExtension
,
631 IN PUSBPORT_RESOURCES Resources
)
633 POHCI_EXTENSION OhciExtension
= ohciExtension
;
634 POHCI_OPERATIONAL_REGISTERS OperationalRegs
;
635 PULONG CommandStatusReg
;
636 PULONG FmIntervalReg
;
638 PULONG InterruptEnableReg
;
640 OHCI_REG_COMMAND_STATUS CommandStatus
;
641 OHCI_REG_INTERRUPT_ENABLE_DISABLE Interrupts
;
642 OHCI_REG_RH_STATUS RhStatus
;
643 OHCI_REG_FRAME_INTERVAL FrameInterval
;
644 ULONG MaxFrameIntervalAdjusting
;
645 OHCI_REG_CONTROL Control
;
647 POHCI_ENDPOINT_DESCRIPTOR IntED
;
650 LARGE_INTEGER SystemTime
;
651 LARGE_INTEGER EndTime
;
654 MPSTATUS MPStatus
= MP_STATUS_SUCCESS
;
656 DPRINT_OHCI("OHCI_StartController: ohciExtension - %p, Resources - %p\n",
660 /* HC on-chip operational registers */
661 OperationalRegs
= (POHCI_OPERATIONAL_REGISTERS
)Resources
->ResourceBase
;
662 OhciExtension
->OperationalRegs
= OperationalRegs
;
664 CommandStatusReg
= (PULONG
)&OperationalRegs
->HcCommandStatus
;
665 FmIntervalReg
= (PULONG
)&OperationalRegs
->HcFmInterval
;
666 ControlReg
= (PULONG
)&OperationalRegs
->HcControl
;
667 InterruptEnableReg
= (PULONG
)&OperationalRegs
->HcInterruptEnable
;
668 RhStatusReg
= (PULONG
)&OperationalRegs
->HcRhStatus
;
670 /* 5.1.1 Initialization */
672 MPStatus
= OHCI_TakeControlHC(OhciExtension
, Resources
);
674 if (MPStatus
!= MP_STATUS_SUCCESS
)
676 DPRINT1("OHCI_StartController: OHCI_TakeControlHC return MPStatus - %x\n",
682 OhciExtension
->HcResourcesVA
= (POHCI_HC_RESOURCES
)Resources
->StartVA
;
683 OhciExtension
->HcResourcesPA
= Resources
->StartPA
;
685 DPRINT_OHCI("OHCI_StartController: HcResourcesVA - %p, HcResourcesPA - %lx\n",
686 OhciExtension
->HcResourcesVA
,
687 OhciExtension
->HcResourcesPA
);
689 /* 5.2.7.2 Interrupt */
691 /* Build structure of interrupt static EDs */
692 for (ix
= 0; ix
< INTERRUPT_ENDPOINTs
; ix
++)
694 IntED
= &OhciExtension
->HcResourcesVA
->InterrruptHeadED
[ix
];
695 IntEdPA
= OhciExtension
->HcResourcesPA
+ FIELD_OFFSET(OHCI_HC_RESOURCES
, InterrruptHeadED
[ix
]);
697 if (ix
== (ENDPOINT_INTERRUPT_1ms
- 1))
704 HeadIndex
= ((ix
- 1) / 2);
706 ASSERT(HeadIndex
>= (ENDPOINT_INTERRUPT_1ms
- 1) &&
707 HeadIndex
< (INTERRUPT_ENDPOINTs
- ENDPOINT_INTERRUPT_32ms
));
709 IntED
->NextED
= OhciExtension
->IntStaticED
[HeadIndex
].PhysicalAddress
;
712 IntED
->EndpointControl
.sKip
= 1;
714 IntED
->TailPointer
= 0;
715 IntED
->HeadPointer
= 0;
717 OhciExtension
->IntStaticED
[ix
].HwED
= IntED
;
718 OhciExtension
->IntStaticED
[ix
].PhysicalAddress
= IntEdPA
;
719 OhciExtension
->IntStaticED
[ix
].HeadIndex
= HeadIndex
;
720 OhciExtension
->IntStaticED
[ix
].pNextED
= &IntED
->NextED
;
721 OhciExtension
->IntStaticED
[ix
].Type
= OHCI_STATIC_ED_TYPE_INTERRUPT
;
723 InitializeListHead(&OhciExtension
->IntStaticED
[ix
].Link
);
726 OhciHCCA
= &OhciExtension
->HcResourcesVA
->HcHCCA
;
727 DPRINT_OHCI("OHCI_InitializeSchedule: OhciHCCA - %p\n", OhciHCCA
);
729 /* Set head pointers which start from HCCA */
730 for (ix
= 0, jx
= (INTERRUPT_ENDPOINTs
- ENDPOINT_INTERRUPT_32ms
);
731 ix
< OHCI_NUMBER_OF_INTERRUPTS
;
734 OhciHCCA
->InterrruptTable
[Balance
[ix
]] =
735 OhciExtension
->IntStaticED
[jx
].PhysicalAddress
;
737 OhciExtension
->IntStaticED
[jx
].pNextED
=
738 (PULONG
)&OhciHCCA
->InterrruptTable
[Balance
[ix
]];
740 OhciExtension
->IntStaticED
[jx
].HccaIndex
= Balance
[ix
];
743 DPRINT_OHCI("OHCI_InitializeSchedule: ix - %x\n", ix
);
745 /* Init static Control and Bulk EDs head pointers which start from HCCA */
746 InitializeListHead(&OhciExtension
->ControlStaticED
.Link
);
748 OhciExtension
->ControlStaticED
.HeadIndex
= ED_EOF
;
749 OhciExtension
->ControlStaticED
.Type
= OHCI_STATIC_ED_TYPE_CONTROL
;
750 OhciExtension
->ControlStaticED
.pNextED
= &OperationalRegs
->HcControlHeadED
;
752 InitializeListHead(&OhciExtension
->BulkStaticED
.Link
);
754 OhciExtension
->BulkStaticED
.HeadIndex
= ED_EOF
;
755 OhciExtension
->BulkStaticED
.Type
= OHCI_STATIC_ED_TYPE_BULK
;
756 OhciExtension
->BulkStaticED
.pNextED
= &OperationalRegs
->HcBulkHeadED
;
758 /* 6.3.1 Frame Timing */
759 FrameInterval
.AsULONG
= READ_REGISTER_ULONG(FmIntervalReg
);
761 MaxFrameIntervalAdjusting
= OHCI_DEFAULT_FRAME_INTERVAL
/ 10; // 10%
763 if ((FrameInterval
.FrameInterval
) < (OHCI_DEFAULT_FRAME_INTERVAL
- MaxFrameIntervalAdjusting
) ||
764 (FrameInterval
.FrameInterval
) > (OHCI_DEFAULT_FRAME_INTERVAL
+ MaxFrameIntervalAdjusting
))
766 FrameInterval
.FrameInterval
= OHCI_DEFAULT_FRAME_INTERVAL
;
769 /* 5.4 FrameInterval Counter */
770 FrameInterval
.FrameIntervalToggle
= 1;
772 /* OHCI_MAXIMUM_OVERHEAD is the maximum overhead per frame */
773 FrameInterval
.FSLargestDataPacket
=
774 ((FrameInterval
.FrameInterval
- OHCI_MAXIMUM_OVERHEAD
) * 6) / 7;
776 OhciExtension
->FrameInterval
= FrameInterval
;
778 DPRINT_OHCI("OHCI_StartController: FrameInterval - %lX\n",
779 FrameInterval
.AsULONG
);
781 /* Reset HostController */
782 CommandStatus
.AsULONG
= 0;
783 CommandStatus
.HostControllerReset
= 1;
785 WRITE_REGISTER_ULONG(CommandStatusReg
, CommandStatus
.AsULONG
);
787 KeStallExecutionProcessor(25);
789 Control
.AsULONG
= READ_REGISTER_ULONG(ControlReg
);
790 Control
.HostControllerFunctionalState
= OHCI_HC_STATE_RESET
;
792 WRITE_REGISTER_ULONG(ControlReg
, Control
.AsULONG
);
794 KeQuerySystemTime(&EndTime
);
795 EndTime
.QuadPart
+= 500 * 10000; // 0.5 sec
799 WRITE_REGISTER_ULONG(FmIntervalReg
, OhciExtension
->FrameInterval
.AsULONG
);
800 FrameInterval
.AsULONG
= READ_REGISTER_ULONG(FmIntervalReg
);
802 KeQuerySystemTime(&SystemTime
);
804 if (SystemTime
.QuadPart
>= EndTime
.QuadPart
)
806 MPStatus
= MP_STATUS_HW_ERROR
;
810 if (FrameInterval
.AsULONG
== OhciExtension
->FrameInterval
.AsULONG
)
812 MPStatus
= MP_STATUS_SUCCESS
;
817 if (MPStatus
!= MP_STATUS_SUCCESS
)
819 DPRINT_OHCI("OHCI_StartController: frame interval not set\n");
823 /* Setup HcPeriodicStart register */
824 WRITE_REGISTER_ULONG(&OperationalRegs
->HcPeriodicStart
,
825 (OhciExtension
->FrameInterval
.FrameInterval
* 9) / 10); //90%
827 /* Setup HcHCCA register */
828 WRITE_REGISTER_ULONG(&OperationalRegs
->HcHCCA
,
829 OhciExtension
->HcResourcesPA
+ FIELD_OFFSET(OHCI_HC_RESOURCES
, HcHCCA
));
831 /* Setup HcInterruptEnable register */
832 Interrupts
.AsULONG
= 0;
834 Interrupts
.SchedulingOverrun
= 1;
835 Interrupts
.WritebackDoneHead
= 1;
836 Interrupts
.UnrecoverableError
= 1;
837 Interrupts
.FrameNumberOverflow
= 1;
838 Interrupts
.OwnershipChange
= 1;
840 WRITE_REGISTER_ULONG(InterruptEnableReg
, Interrupts
.AsULONG
);
842 /* Setup HcControl register */
843 Control
.AsULONG
= READ_REGISTER_ULONG(ControlReg
);
845 Control
.ControlBulkServiceRatio
= 0; // FIXME (1 : 1)
846 Control
.PeriodicListEnable
= 1;
847 Control
.IsochronousEnable
= 1;
848 Control
.ControlListEnable
= 1;
849 Control
.BulkListEnable
= 1;
850 Control
.HostControllerFunctionalState
= OHCI_HC_STATE_OPERATIONAL
;
852 WRITE_REGISTER_ULONG(ControlReg
, Control
.AsULONG
);
854 /* Setup HcRhStatus register */
855 RhStatus
.AsULONG
= 0;
856 RhStatus
.SetGlobalPower
= 1;
858 WRITE_REGISTER_ULONG(RhStatusReg
, RhStatus
.AsULONG
);
860 return MP_STATUS_SUCCESS
;
865 OHCI_StopController(IN PVOID ohciExtension
,
866 IN BOOLEAN IsDoDisableInterrupts
)
868 POHCI_EXTENSION OhciExtension
= ohciExtension
;
869 POHCI_OPERATIONAL_REGISTERS OperationalRegs
;
871 PULONG InterruptDisableReg
;
872 PULONG InterruptStatusReg
;
873 OHCI_REG_CONTROL Control
;
874 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable
;
875 OHCI_REG_INTERRUPT_STATUS IntStatus
;
877 DPRINT("OHCI_StopController: ... \n");
879 OperationalRegs
= OhciExtension
->OperationalRegs
;
881 ControlReg
= (PULONG
)&OperationalRegs
->HcControl
;
882 InterruptDisableReg
= (PULONG
)&OperationalRegs
->HcInterruptDisable
;
883 InterruptStatusReg
= (PULONG
)&OperationalRegs
->HcInterruptStatus
;
885 /* Setup HcControl register */
886 Control
.AsULONG
= READ_REGISTER_ULONG(ControlReg
);
888 Control
.PeriodicListEnable
= 0;
889 Control
.IsochronousEnable
= 0;
890 Control
.ControlListEnable
= 0;
891 Control
.BulkListEnable
= 0;
892 Control
.HostControllerFunctionalState
= OHCI_HC_STATE_SUSPEND
;
893 Control
.RemoteWakeupEnable
= 0;
895 WRITE_REGISTER_ULONG(ControlReg
, Control
.AsULONG
);
897 /* Disable interrupt generations */
898 IntDisable
.AsULONG
= 0xFFFFFFFF;
899 WRITE_REGISTER_ULONG(InterruptDisableReg
, IntDisable
.AsULONG
);
901 /* Clear all bits in HcInterruptStatus register */
902 IntStatus
.AsULONG
= 0xFFFFFFFF;
903 WRITE_REGISTER_ULONG(InterruptStatusReg
, IntStatus
.AsULONG
);
908 OHCI_SuspendController(IN PVOID ohciExtension
)
910 POHCI_EXTENSION OhciExtension
= ohciExtension
;
911 POHCI_OPERATIONAL_REGISTERS OperationalRegs
;
913 PULONG InterruptEnableReg
;
914 OHCI_REG_CONTROL Control
;
915 OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptReg
;
917 DPRINT("OHCI_SuspendController: ... \n");
919 OperationalRegs
= OhciExtension
->OperationalRegs
;
920 ControlReg
= (PULONG
)&OperationalRegs
->HcControl
;
921 InterruptEnableReg
= (PULONG
)&OperationalRegs
->HcInterruptEnable
;
923 /* Disable all interrupt generations */
924 WRITE_REGISTER_ULONG(&OperationalRegs
->HcInterruptDisable
.AsULONG
,
927 /* Clear all bits in HcInterruptStatus register */
928 WRITE_REGISTER_ULONG(&OperationalRegs
->HcInterruptStatus
.AsULONG
,
931 /* Setup HcControl register */
932 Control
.AsULONG
= READ_REGISTER_ULONG(ControlReg
);
933 Control
.HostControllerFunctionalState
= OHCI_HC_STATE_SUSPEND
;
934 Control
.RemoteWakeupEnable
= 1;
936 WRITE_REGISTER_ULONG(ControlReg
, Control
.AsULONG
);
938 /* Setup HcInterruptEnable register */
939 InterruptReg
.AsULONG
= 0;
940 InterruptReg
.ResumeDetected
= 1;
941 InterruptReg
.UnrecoverableError
= 1;
942 InterruptReg
.RootHubStatusChange
= 1;
943 InterruptReg
.MasterInterruptEnable
= 1;
945 WRITE_REGISTER_ULONG(InterruptEnableReg
, InterruptReg
.AsULONG
);
950 OHCI_ResumeController(IN PVOID ohciExtension
)
952 POHCI_EXTENSION OhciExtension
= ohciExtension
;
953 POHCI_OPERATIONAL_REGISTERS OperationalRegs
;
955 PULONG InterruptEnableReg
;
957 OHCI_REG_CONTROL control
;
958 OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptReg
;
960 DPRINT("OHCI_ResumeController \n");
962 OperationalRegs
= OhciExtension
->OperationalRegs
;
963 ControlReg
= (PULONG
)&OperationalRegs
->HcControl
;
964 InterruptEnableReg
= (PULONG
)&OperationalRegs
->HcInterruptEnable
;
966 control
.AsULONG
= READ_REGISTER_ULONG(ControlReg
);
968 if (control
.HostControllerFunctionalState
!= OHCI_HC_STATE_SUSPEND
)
969 return MP_STATUS_HW_ERROR
;
971 HcHCCA
= &OhciExtension
->HcResourcesVA
->HcHCCA
;
974 /* Setup HcControl register */
975 control
.HostControllerFunctionalState
= OHCI_HC_STATE_OPERATIONAL
;
976 WRITE_REGISTER_ULONG(ControlReg
, control
.AsULONG
);
978 /* Setup HcInterruptEnable register */
979 InterruptReg
.AsULONG
= 0;
980 InterruptReg
.SchedulingOverrun
= 1;
981 InterruptReg
.WritebackDoneHead
= 1;
982 InterruptReg
.UnrecoverableError
= 1;
983 InterruptReg
.FrameNumberOverflow
= 1;
984 InterruptReg
.OwnershipChange
= 1;
986 WRITE_REGISTER_ULONG(InterruptEnableReg
, InterruptReg
.AsULONG
);
987 WRITE_REGISTER_ULONG(ControlReg
, control
.AsULONG
);
989 return MP_STATUS_SUCCESS
;
994 OHCI_HardwarePresent(IN POHCI_EXTENSION OhciExtension
,
995 IN BOOLEAN IsInvalidateController
)
997 POHCI_OPERATIONAL_REGISTERS OperationalRegs
;
998 PULONG CommandStatusReg
;
1000 OperationalRegs
= OhciExtension
->OperationalRegs
;
1001 CommandStatusReg
= (PULONG
)&OperationalRegs
->HcCommandStatus
;
1003 if (READ_REGISTER_ULONG(CommandStatusReg
) != 0xFFFFFFFF)
1006 DPRINT1("OHCI_HardwarePresent: IsInvalidateController - %x\n",
1007 IsInvalidateController
);
1009 if (IsInvalidateController
)
1011 RegPacket
.UsbPortInvalidateController(OhciExtension
,
1012 USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE
);
1020 OHCI_InterruptService(IN PVOID ohciExtension
)
1022 POHCI_EXTENSION OhciExtension
= ohciExtension
;
1023 POHCI_OPERATIONAL_REGISTERS OperationalRegs
;
1024 OHCI_REG_INTERRUPT_STATUS IntStatus
;
1025 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable
;
1026 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable
;
1027 BOOLEAN HardwarePresent
= FALSE
;
1029 DPRINT_OHCI("OHCI_Interrupt: Ext %p\n", OhciExtension
);
1031 OperationalRegs
= OhciExtension
->OperationalRegs
;
1033 HardwarePresent
= OHCI_HardwarePresent(OhciExtension
, FALSE
);
1035 if (!HardwarePresent
)
1038 IntEnable
.AsULONG
= READ_REGISTER_ULONG((PULONG
)&OperationalRegs
->HcInterruptEnable
);
1039 IntStatus
.AsULONG
= READ_REGISTER_ULONG((PULONG
)&OperationalRegs
->HcInterruptStatus
) & IntEnable
.AsULONG
;
1041 if ((IntStatus
.AsULONG
== 0) || (IntEnable
.MasterInterruptEnable
== 0))
1044 if (IntStatus
.UnrecoverableError
)
1045 DPRINT1("OHCI_InterruptService: IntStatus.UnrecoverableError\n");
1047 if (IntStatus
.FrameNumberOverflow
)
1053 HcHCCA
= &OhciExtension
->HcResourcesVA
->HcHCCA
;
1055 DPRINT("FrameNumberOverflow %lX\n", HcHCCA
->FrameNumber
);
1057 hp
= OhciExtension
->FrameHighPart
;
1058 fm
= HcHCCA
->FrameNumber
;
1060 /* Increment value of FrameHighPart */
1061 OhciExtension
->FrameHighPart
+= 1 * (1 << 16) - ((hp
^ fm
) & 0x8000);
1064 /* Disable interrupt generation */
1065 IntDisable
.AsULONG
= 0;
1066 IntDisable
.MasterInterruptEnable
= 1;
1067 WRITE_REGISTER_ULONG((PULONG
)&OperationalRegs
->HcInterruptDisable
,
1068 IntDisable
.AsULONG
);
1075 OHCI_InterruptDpc(IN PVOID ohciExtension
,
1076 IN BOOLEAN IsDoEnableInterrupts
)
1078 POHCI_EXTENSION OhciExtension
= ohciExtension
;
1079 POHCI_OPERATIONAL_REGISTERS OperationalRegs
;
1080 PULONG InterruptDisableReg
;
1081 PULONG InterruptEnableReg
;
1082 PULONG InterruptStatusReg
;
1083 OHCI_REG_INTERRUPT_STATUS IntStatus
;
1084 OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptBits
;
1087 OperationalRegs
= OhciExtension
->OperationalRegs
;
1089 InterruptEnableReg
= (PULONG
)&OperationalRegs
->HcInterruptEnable
;
1090 InterruptDisableReg
= (PULONG
)&OperationalRegs
->HcInterruptDisable
;
1091 InterruptStatusReg
= (PULONG
)&OperationalRegs
->HcInterruptStatus
;
1093 DPRINT_OHCI("OHCI_InterruptDpc: OhciExtension - %p, IsDoEnableInterrupts - %x\n",
1095 IsDoEnableInterrupts
);
1097 IntStatus
.AsULONG
= READ_REGISTER_ULONG(InterruptStatusReg
);
1099 if (IntStatus
.RootHubStatusChange
)
1101 DPRINT_OHCI("OHCI_InterruptDpc: RootHubStatusChange\n");
1102 RegPacket
.UsbPortInvalidateRootHub(OhciExtension
);
1105 if (IntStatus
.WritebackDoneHead
)
1107 DPRINT_OHCI("OHCI_InterruptDpc: WritebackDoneHead\n");
1109 HcHCCA
= &OhciExtension
->HcResourcesVA
->HcHCCA
;
1110 HcHCCA
->DoneHead
= 0;
1112 RegPacket
.UsbPortInvalidateEndpoint(OhciExtension
, NULL
);
1115 if (IntStatus
.StartofFrame
)
1117 /* Disable interrupt generation due to Start of Frame */
1118 InterruptBits
.AsULONG
= 0;
1119 InterruptBits
.StartofFrame
= 1;
1121 WRITE_REGISTER_ULONG(InterruptDisableReg
, InterruptBits
.AsULONG
);
1124 if (IntStatus
.ResumeDetected
)
1125 DPRINT1("OHCI_IntDpc: ResumeDetected\n");
1127 if (IntStatus
.UnrecoverableError
)
1129 DPRINT1("OHCI_IntDpc: UnrecoverableError\n");
1132 WRITE_REGISTER_ULONG(InterruptStatusReg
, IntStatus
.AsULONG
);
1134 if (IsDoEnableInterrupts
)
1136 /* Enable interrupt generation */
1137 InterruptBits
.AsULONG
= 0;
1138 InterruptBits
.MasterInterruptEnable
= 1;
1140 WRITE_REGISTER_ULONG(InterruptEnableReg
, InterruptBits
.AsULONG
);
1145 * @brief Forms the next General Transfer Descriptor for the current transfer
1147 * @param[in] OhciExtension The ohci extension
1148 * @param[in] TransferedLen The consolidated length of all previous descriptors' buffers
1149 * @param[in] OhciTransfer The ohci transfer
1150 * @param[out] TD The transfer descriptor we are forming
1151 * @param[in] SGList The scatter/gather list
1153 * @return The length of all previous buffers summed with the length of the current buffer
1157 OHCI_MapTransferToTD(IN POHCI_EXTENSION OhciExtension
,
1158 IN ULONG TransferedLen
,
1159 IN POHCI_TRANSFER OhciTransfer
,
1160 OUT POHCI_HCD_TD TD
,
1161 IN PUSBPORT_SCATTER_GATHER_LIST SGList
)
1163 PUSBPORT_SCATTER_GATHER_ELEMENT SgElement
;
1164 ULONG SgIdx
, CurrentTransferLen
, BufferEnd
, CurrentBuffer
;
1165 ULONG TransferDataLeft
= OhciTransfer
->TransferParameters
->TransferBufferLength
- TransferedLen
;
1167 DPRINT_OHCI("OHCI_MapTransferToTD: TransferedLen - %x\n", TransferedLen
);
1169 for (SgIdx
= 0; SgIdx
< SGList
->SgElementCount
; SgIdx
++)
1171 SgElement
= &SGList
->SgElement
[SgIdx
];
1173 if (TransferedLen
>= SgElement
->SgOffset
&&
1174 TransferedLen
< SgElement
->SgOffset
+ SgElement
->SgTransferLength
)
1180 DPRINT_OHCI("OHCI_MapTransferToTD: SgIdx - %x, SgCount - %x\n",
1182 SGList
->SgElementCount
);
1184 ASSERT(SgIdx
< SGList
->SgElementCount
);
1185 ASSERT(TransferedLen
== SgElement
->SgOffset
);
1187 /* The buffer for a TD can be 0 to 8192 bytes long,
1188 * and can span within mo more than two 4k pages (see OpenHCI spec 3.3.2)
1189 * CurrentBuffer - the (physical) address of the first byte in the buffer
1190 * BufferEnd - the address of the last byte in the buffer. It can be on a different physical 4k page
1191 * when a controller will reach the end of a page from CurrentBuffer, it will take the first 20 bits
1192 * of the BufferEnd as a next address (OpenHCI spec, 4.3.1.3.1)
1195 CurrentBuffer
= SgElement
->SgPhysicalAddress
.LowPart
;
1197 if (TransferDataLeft
<= SgElement
->SgTransferLength
)
1199 CurrentTransferLen
= TransferDataLeft
;
1200 BufferEnd
= SgElement
->SgPhysicalAddress
.LowPart
+ CurrentTransferLen
- 1;
1204 PUSBPORT_SCATTER_GATHER_ELEMENT SgNextElement
;
1205 ASSERT(SGList
->SgElementCount
- SgIdx
> 1);
1207 SgNextElement
= &SGList
->SgElement
[SgIdx
+ 1];
1209 TransferDataLeft
-= SgElement
->SgTransferLength
;
1210 CurrentTransferLen
= SgElement
->SgTransferLength
;
1212 if (TransferDataLeft
<= SgNextElement
->SgTransferLength
)
1214 CurrentTransferLen
+= TransferDataLeft
;
1215 BufferEnd
= SgNextElement
->SgPhysicalAddress
.LowPart
+ TransferDataLeft
- 1;
1219 CurrentTransferLen
+= SgNextElement
->SgTransferLength
;
1220 BufferEnd
= SgNextElement
->SgPhysicalAddress
.LowPart
+ SgNextElement
->SgTransferLength
- 1;
1224 TD
->HwTD
.gTD
.CurrentBuffer
= CurrentBuffer
;
1225 TD
->HwTD
.gTD
.BufferEnd
= BufferEnd
;
1226 TD
->TransferLen
= CurrentTransferLen
;
1228 return TransferedLen
+ CurrentTransferLen
;
1233 OHCI_AllocateTD(IN POHCI_EXTENSION OhciExtension
,
1234 IN POHCI_ENDPOINT OhciEndpoint
)
1238 DPRINT_OHCI("OHCI_AllocateTD: ... \n");
1240 TD
= OhciEndpoint
->FirstTD
;
1242 while (TD
->Flags
& OHCI_HCD_TD_FLAG_ALLOCATED
)
1247 TD
->Flags
|= OHCI_HCD_TD_FLAG_ALLOCATED
;
1254 OHCI_RemainTDs(IN POHCI_EXTENSION OhciExtension
,
1255 IN POHCI_ENDPOINT OhciEndpoint
)
1262 DPRINT_OHCI("OHCI_RemainTDs: ... \n");
1264 MaxTDs
= OhciEndpoint
->MaxTransferDescriptors
;
1265 TD
= OhciEndpoint
->FirstTD
;
1269 for (ix
= 0; ix
< MaxTDs
; ix
++)
1271 if (!(TD
->Flags
& OHCI_HCD_TD_FLAG_ALLOCATED
))
1282 OHCI_ControlTransfer(IN POHCI_EXTENSION OhciExtension
,
1283 IN POHCI_ENDPOINT OhciEndpoint
,
1284 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters
,
1285 IN POHCI_TRANSFER OhciTransfer
,
1286 IN PUSBPORT_SCATTER_GATHER_LIST SGList
)
1288 POHCI_HCD_TD FirstTD
;
1292 POHCI_HCD_TD PrevTD
;
1293 POHCI_HCD_TD NextTD
;
1295 ULONG TransferedLen
;
1299 DPRINT_OHCI("OHCI_ControlTransfer: Ext %p, Endpoint %p\n",
1303 MaxTDs
= OHCI_RemainTDs(OhciExtension
, OhciEndpoint
);
1305 if ((SGList
->SgElementCount
+ OHCI_NON_DATA_CONTROL_TDS
) > MaxTDs
)
1306 return MP_STATUS_FAILURE
;
1308 FirstTD
= OhciEndpoint
->HcdTailP
;
1309 FirstTD
->HwTD
.gTD
.Control
.DelayInterrupt
= OHCI_TD_INTERRUPT_NONE
;
1311 FirstTD
->HwTD
.gTD
.NextTD
= 0;
1312 FirstTD
->HwTD
.gTD
.CurrentBuffer
= 0;
1313 FirstTD
->HwTD
.gTD
.BufferEnd
= 0;
1315 FirstTD
->Flags
|= OHCI_HCD_TD_FLAG_PROCESSED
;
1316 FirstTD
->NextHcdTD
= 0;
1317 FirstTD
->OhciTransfer
= OhciTransfer
;
1319 FirstTD
->HwTD
.Padded
[0] = 0;
1320 FirstTD
->HwTD
.Padded
[1] = 0;
1322 OhciTransfer
->PendingTDs
++;
1324 RtlCopyMemory(&FirstTD
->HwTD
.SetupPacket
,
1325 &TransferParameters
->SetupPacket
,
1326 sizeof(FirstTD
->HwTD
.SetupPacket
));
1328 FirstTdPA
= FirstTD
->PhysicalAddress
;
1330 FirstTD
->HwTD
.gTD
.CurrentBuffer
= FirstTdPA
+ FIELD_OFFSET(OHCI_HCD_TD
, HwTD
.SetupPacket
);
1332 BufferEnd
= FirstTdPA
+ FIELD_OFFSET(OHCI_HCD_TD
, HwTD
.SetupPacket
) +
1333 sizeof(USB_DEFAULT_PIPE_SETUP_PACKET
) - 1;
1335 FirstTD
->HwTD
.gTD
.BufferEnd
= BufferEnd
;
1337 FirstTD
->HwTD
.gTD
.Control
.AsULONG
= 0;
1338 FirstTD
->HwTD
.gTD
.Control
.DelayInterrupt
= OHCI_TD_INTERRUPT_NONE
;
1339 FirstTD
->HwTD
.gTD
.Control
.ConditionCode
= OHCI_TD_CONDITION_NOT_ACCESSED
;
1340 FirstTD
->HwTD
.gTD
.Control
.DataToggle
= OHCI_TD_DATA_TOGGLE_DATA0
;
1342 TD2
= OHCI_AllocateTD(OhciExtension
, OhciEndpoint
);
1344 TD2
->HwTD
.gTD
.Control
.DelayInterrupt
= OHCI_TD_INTERRUPT_NONE
;
1345 TD2
->HwTD
.gTD
.CurrentBuffer
= 0;
1346 TD2
->HwTD
.gTD
.BufferEnd
= 0;
1347 TD2
->HwTD
.gTD
.NextTD
= 0;
1349 TD2
->Flags
|= OHCI_HCD_TD_FLAG_PROCESSED
;
1351 TD2
->OhciTransfer
= OhciTransfer
;
1353 RtlZeroMemory(&TD2
->HwTD
.SetupPacket
,
1354 sizeof(TD2
->HwTD
.SetupPacket
));
1356 TD2
->HwTD
.Padded
[0] = 0;
1357 TD2
->HwTD
.Padded
[1] = 0;
1362 PrevTD
->HwTD
.gTD
.NextTD
= TD2
->PhysicalAddress
;
1363 PrevTD
->NextHcdTD
= TD2
;
1366 DataToggle
= OHCI_TD_DATA_TOGGLE_DATA1
;
1368 while (TransferedLen
< TransferParameters
->TransferBufferLength
)
1370 OhciTransfer
->PendingTDs
++;
1372 if (TransferParameters
->TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1373 TD
->HwTD
.gTD
.Control
.DirectionPID
= OHCI_TD_DIRECTION_PID_IN
;
1375 TD
->HwTD
.gTD
.Control
.DirectionPID
= OHCI_TD_DIRECTION_PID_OUT
;
1377 TD
->HwTD
.gTD
.Control
.DelayInterrupt
= OHCI_TD_INTERRUPT_NONE
;
1378 TD
->HwTD
.gTD
.Control
.DataToggle
= DataToggle
;
1379 TD
->HwTD
.gTD
.Control
.ConditionCode
= OHCI_TD_CONDITION_NOT_ACCESSED
;
1381 DataToggle
= OHCI_TD_DATA_TOGGLE_FROM_ED
;
1383 TransferedLen
= OHCI_MapTransferToTD(OhciExtension
,
1391 TD
= OHCI_AllocateTD(OhciExtension
, OhciEndpoint
);
1393 TD
->Flags
|= OHCI_HCD_TD_FLAG_PROCESSED
;
1395 TD
->HwTD
.gTD
.NextTD
= 0;
1396 TD
->HwTD
.gTD
.Control
.DelayInterrupt
= OHCI_TD_INTERRUPT_NONE
;
1399 TD
->OhciTransfer
= OhciTransfer
;
1401 TD
->HwTD
.gTD
.CurrentBuffer
= 0;
1402 TD
->HwTD
.gTD
.BufferEnd
= 0;
1404 RtlZeroMemory(&TD
->HwTD
.SetupPacket
,
1405 sizeof(TD
->HwTD
.SetupPacket
));
1407 TD
->HwTD
.Padded
[0] = 0;
1408 TD
->HwTD
.Padded
[1] = 0;
1410 PrevTD
->HwTD
.gTD
.NextTD
= TD
->PhysicalAddress
;
1411 PrevTD
->NextHcdTD
= TD
;
1414 if (TransferParameters
->TransferFlags
& USBD_SHORT_TRANSFER_OK
)
1416 PrevTD
->HwTD
.gTD
.Control
.BufferRounding
= TRUE
;
1417 OhciTransfer
->Flags
|= OHCI_TRANSFER_FLAGS_SHORT_TRANSFER_OK
;
1420 TD
->HwTD
.gTD
.CurrentBuffer
= 0;
1421 TD
->HwTD
.gTD
.BufferEnd
= 0;
1423 TD
->Flags
|= OHCI_HCD_TD_FLAG_CONTROL_STATUS
;
1424 TD
->TransferLen
= 0;
1426 TD
->HwTD
.gTD
.Control
.AsULONG
= 0;
1428 if ((TransferParameters
->TransferFlags
& USBD_TRANSFER_DIRECTION_IN
) != 0)
1430 TD
->HwTD
.gTD
.Control
.DirectionPID
= OHCI_TD_DIRECTION_PID_OUT
;
1434 TD
->HwTD
.gTD
.Control
.BufferRounding
= TRUE
;
1435 TD
->HwTD
.gTD
.Control
.DirectionPID
= OHCI_TD_DIRECTION_PID_IN
;
1438 TD
->HwTD
.gTD
.Control
.DataToggle
= OHCI_TD_DATA_TOGGLE_DATA1
;
1439 TD
->HwTD
.gTD
.Control
.ConditionCode
= OHCI_TD_CONDITION_NOT_ACCESSED
;
1441 OhciTransfer
->PendingTDs
++;
1442 OhciTransfer
->ControlStatusTD
= TD
;
1444 NextTD
= OHCI_AllocateTD(OhciExtension
, OhciEndpoint
);
1446 TD
->HwTD
.gTD
.NextTD
= NextTD
->PhysicalAddress
;
1447 TD
->NextHcdTD
= NextTD
;
1449 NextTD
->NextHcdTD
= 0;
1450 NextTD
->HwTD
.gTD
.NextTD
= 0;
1452 OhciTransfer
->NextTD
= NextTD
;
1453 OhciEndpoint
->HcdTailP
= NextTD
;
1455 OhciEndpoint
->HcdED
->HwED
.TailPointer
= NextTD
->PhysicalAddress
;
1457 OHCI_EnableList(OhciExtension
, OhciEndpoint
);
1459 return MP_STATUS_SUCCESS
;
1463 * @brief Creates the transfer descriptor chain for the given transfer's buffer
1464 * and attaches it to a given endpoint (for bulk or interrupt transfers)
1466 * @param[in] OhciExtension The ohci extension
1467 * @param[in] OhciEndpoint The ohci endpoint
1468 * @param[in] TransferParameters The transfer parameters
1469 * @param[in] OhciTransfer The ohci transfer
1470 * @param[in] SGList The scatter/gather list
1472 * @return MP_STATUS_SUCCESS or MP_STATUS_FAILURE if there are not enough TDs left
1476 OHCI_BulkOrInterruptTransfer(IN POHCI_EXTENSION OhciExtension
,
1477 IN POHCI_ENDPOINT OhciEndpoint
,
1478 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters
,
1479 IN POHCI_TRANSFER OhciTransfer
,
1480 IN PUSBPORT_SCATTER_GATHER_LIST SGList
)
1483 POHCI_HCD_TD PrevTD
;
1484 ULONG TransferedLen
;
1487 DPRINT_OHCI("OHCI_BulkOrInterruptTransfer: ... \n");
1489 MaxTDs
= OHCI_RemainTDs(OhciExtension
, OhciEndpoint
);
1491 if (SGList
->SgElementCount
> MaxTDs
)
1492 return MP_STATUS_FAILURE
;
1494 TD
= OhciEndpoint
->HcdTailP
;
1500 TD
->HwTD
.gTD
.Control
.AsULONG
= 0;
1501 TD
->HwTD
.gTD
.Control
.DelayInterrupt
= OHCI_TD_INTERRUPT_NONE
;
1502 TD
->HwTD
.gTD
.Control
.ConditionCode
= OHCI_TD_CONDITION_NOT_ACCESSED
;
1504 if (TransferParameters
->TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
1506 TD
->HwTD
.gTD
.Control
.BufferRounding
= 0;
1507 TD
->HwTD
.gTD
.Control
.DirectionPID
= OHCI_TD_DIRECTION_PID_IN
;
1511 TD
->HwTD
.gTD
.Control
.BufferRounding
= TRUE
;
1512 TD
->HwTD
.gTD
.Control
.DirectionPID
= OHCI_TD_DIRECTION_PID_OUT
;
1515 TD
->HwTD
.gTD
.CurrentBuffer
= 0;
1516 TD
->HwTD
.gTD
.NextTD
= 0;
1517 TD
->HwTD
.gTD
.BufferEnd
= 0;
1519 RtlZeroMemory(&TD
->HwTD
.SetupPacket
,
1520 sizeof(TD
->HwTD
.SetupPacket
));
1522 TD
->HwTD
.Padded
[0] = 0;
1523 TD
->HwTD
.Padded
[1] = 0;
1525 TD
->Flags
|= OHCI_HCD_TD_FLAG_PROCESSED
;
1526 TD
->OhciTransfer
= OhciTransfer
;
1529 if (TransferParameters
->TransferBufferLength
)
1531 TransferedLen
= OHCI_MapTransferToTD(OhciExtension
,
1539 ASSERT(SGList
->SgElementCount
== 0);
1541 TD
->HwTD
.gTD
.CurrentBuffer
= 0;
1542 TD
->HwTD
.gTD
.BufferEnd
= 0;
1544 TD
->TransferLen
= 0;
1549 TD
= OHCI_AllocateTD(OhciExtension
, OhciEndpoint
);
1550 OhciTransfer
->PendingTDs
++;
1552 PrevTD
->HwTD
.gTD
.NextTD
= TD
->PhysicalAddress
;
1553 PrevTD
->NextHcdTD
= TD
;
1555 while (TransferedLen
< TransferParameters
->TransferBufferLength
);
1557 if (TransferParameters
->TransferFlags
& USBD_SHORT_TRANSFER_OK
)
1559 PrevTD
->HwTD
.gTD
.Control
.BufferRounding
= TRUE
;
1560 OhciTransfer
->Flags
|= OHCI_TRANSFER_FLAGS_SHORT_TRANSFER_OK
;
1563 PrevTD
->HwTD
.gTD
.Control
.DelayInterrupt
= OHCI_TD_INTERRUPT_IMMEDIATE
;
1564 PrevTD
->HwTD
.gTD
.NextTD
= TD
->PhysicalAddress
;
1565 PrevTD
->NextHcdTD
= TD
;
1567 /* The last TD in a chain is not used in a transfer. The controller does not access it
1568 * so it will be used for chaining a next transfer to it (OpenHCI spec, 4.6)
1570 TD
->HwTD
.gTD
.NextTD
= 0;
1573 OhciTransfer
->NextTD
= TD
;
1574 OhciEndpoint
->HcdTailP
= TD
;
1576 OhciEndpoint
->HcdED
->HwED
.TailPointer
= TD
->PhysicalAddress
;
1578 OHCI_EnableList(OhciExtension
, OhciEndpoint
);
1580 return MP_STATUS_SUCCESS
;
1585 OHCI_SubmitTransfer(IN PVOID ohciExtension
,
1586 IN PVOID ohciEndpoint
,
1587 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters
,
1588 IN PVOID ohciTransfer
,
1589 IN PUSBPORT_SCATTER_GATHER_LIST SGList
)
1591 POHCI_EXTENSION OhciExtension
= ohciExtension
;
1592 POHCI_ENDPOINT OhciEndpoint
= ohciEndpoint
;
1593 POHCI_TRANSFER OhciTransfer
= ohciTransfer
;
1596 DPRINT_OHCI("OHCI_SubmitTransfer: ... \n");
1598 RtlZeroMemory(OhciTransfer
, sizeof(OHCI_TRANSFER
));
1600 OhciTransfer
->TransferParameters
= TransferParameters
;
1601 OhciTransfer
->OhciEndpoint
= OhciEndpoint
;
1603 TransferType
= OhciEndpoint
->EndpointProperties
.TransferType
;
1605 if (TransferType
== USBPORT_TRANSFER_TYPE_CONTROL
)
1607 return OHCI_ControlTransfer(OhciExtension
,
1614 if (TransferType
== USBPORT_TRANSFER_TYPE_BULK
||
1615 TransferType
== USBPORT_TRANSFER_TYPE_INTERRUPT
)
1617 return OHCI_BulkOrInterruptTransfer(OhciExtension
,
1624 return MP_STATUS_FAILURE
;
1629 OHCI_SubmitIsoTransfer(IN PVOID ohciExtension
,
1630 IN PVOID ohciEndpoint
,
1631 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters
,
1632 IN PVOID ohciTransfer
,
1633 IN PVOID isoParameters
)
1635 DPRINT1("OHCI_SubmitIsoTransfer: UNIMPLEMENTED. FIXME\n");
1636 return MP_STATUS_SUCCESS
;
1641 OHCI_ProcessDoneTD(IN POHCI_EXTENSION OhciExtension
,
1643 IN BOOLEAN IsPortComplete
)
1645 POHCI_TRANSFER OhciTransfer
;
1646 POHCI_ENDPOINT OhciEndpoint
;
1651 DPRINT_OHCI("OHCI_ProcessDoneTD: ... \n");
1653 OhciTransfer
= TD
->OhciTransfer
;
1654 OhciEndpoint
= OhciTransfer
->OhciEndpoint
;
1656 OhciTransfer
->PendingTDs
--;
1658 Buffer
= TD
->HwTD
.gTD
.CurrentBuffer
;
1659 BufferEnd
= TD
->HwTD
.gTD
.BufferEnd
;
1661 if (TD
->Flags
& OHCI_HCD_TD_FLAG_NOT_ACCESSED
)
1663 TD
->HwTD
.gTD
.Control
.ConditionCode
= OHCI_TD_CONDITION_NO_ERROR
;
1667 if (TD
->HwTD
.gTD
.CurrentBuffer
)
1669 if (TD
->TransferLen
)
1671 Length
= (BufferEnd
& (PAGE_SIZE
- 1)) -
1672 (Buffer
& (PAGE_SIZE
- 1));
1676 if (Buffer
>> PAGE_SHIFT
!= BufferEnd
>> PAGE_SHIFT
)
1677 Length
+= PAGE_SIZE
;
1679 TD
->TransferLen
-= Length
;
1683 if (TD
->HwTD
.gTD
.Control
.DirectionPID
!= OHCI_TD_DIRECTION_PID_SETUP
)
1684 OhciTransfer
->TransferLen
+= TD
->TransferLen
;
1686 if (TD
->HwTD
.gTD
.Control
.ConditionCode
)
1688 OhciTransfer
->USBDStatus
= USBD_STATUS_HALTED
|
1689 TD
->HwTD
.gTD
.Control
.ConditionCode
;
1694 TD
->HwTD
.gTD
.NextTD
= 0;
1695 TD
->OhciTransfer
= 0;
1697 TD
->DoneLink
.Flink
= NULL
;
1698 TD
->DoneLink
.Blink
= NULL
;
1700 if (IsPortComplete
&& (OhciTransfer
->PendingTDs
== 0))
1702 RegPacket
.UsbPortCompleteTransfer(OhciExtension
,
1704 OhciTransfer
->TransferParameters
,
1705 OhciTransfer
->USBDStatus
,
1706 OhciTransfer
->TransferLen
);
1712 OHCI_ProcessDoneIsoTD(IN POHCI_EXTENSION OhciExtension
,
1714 IN BOOLEAN IsPortComplete
)
1716 DPRINT1("OHCI_ProcessDoneIsoTD: UNIMPLEMENTED. FIXME\n");
1721 OHCI_AbortTransfer(IN PVOID ohciExtension
,
1722 IN PVOID ohciEndpoint
,
1723 IN PVOID ohciTransfer
,
1724 IN OUT PULONG CompletedLength
)
1726 POHCI_EXTENSION OhciExtension
= ohciExtension
;
1727 POHCI_ENDPOINT OhciEndpoint
= ohciEndpoint
;
1728 POHCI_TRANSFER OhciTransfer
= ohciTransfer
;
1729 POHCI_TRANSFER TmpTransfer
;
1732 POHCI_HCD_TD NextTD
;
1734 POHCI_HCD_TD PrevTD
;
1735 POHCI_HCD_TD LastTD
;
1736 POHCI_HCD_TD td
= NULL
;
1738 BOOLEAN IsIsoEndpoint
= FALSE
;
1739 BOOLEAN IsProcessed
= FALSE
;
1741 DPRINT("OHCI_AbortTransfer: ohciEndpoint - %p, ohciTransfer - %p\n",
1745 if (OhciEndpoint
->EndpointProperties
.TransferType
==
1746 USBPORT_TRANSFER_TYPE_ISOCHRONOUS
)
1748 IsIsoEndpoint
= TRUE
;
1751 ED
= OhciEndpoint
->HcdED
;
1752 NextTdPA
= ED
->HwED
.HeadPointer
& OHCI_ED_HEAD_POINTER_MASK
;
1754 NextTD
= RegPacket
.UsbPortGetMappedVirtualAddress(NextTdPA
,
1758 if (NextTD
->OhciTransfer
== OhciTransfer
)
1760 LastTD
= OhciTransfer
->NextTD
;
1762 ED
->HwED
.HeadPointer
= LastTD
->PhysicalAddress
|
1763 (ED
->HwED
.HeadPointer
& OHCI_ED_HEAD_POINTER_CARRY
);
1765 OhciEndpoint
->HcdHeadP
= LastTD
;
1767 for (ix
= 0; ix
< OhciEndpoint
->MaxTransferDescriptors
; ix
++)
1769 TD
= &OhciEndpoint
->FirstTD
[ix
];
1771 if (TD
->OhciTransfer
== OhciTransfer
)
1774 OHCI_ProcessDoneIsoTD(OhciExtension
, TD
, FALSE
);
1776 OHCI_ProcessDoneTD(OhciExtension
, TD
, FALSE
);
1780 *CompletedLength
= OhciTransfer
->TransferLen
;
1784 TD
= OhciEndpoint
->HcdHeadP
;
1791 if (TD
->OhciTransfer
== ohciTransfer
)
1796 if (PrevTD
== OhciEndpoint
->HcdHeadP
)
1797 OhciEndpoint
->HcdHeadP
= TD
;
1800 OHCI_ProcessDoneIsoTD(OhciExtension
, PrevTD
, FALSE
);
1802 OHCI_ProcessDoneTD(OhciExtension
, PrevTD
, FALSE
);
1811 while (TD
!= NextTD
);
1815 TD
= OhciEndpoint
->HcdHeadP
;
1820 while (TD
!= OhciEndpoint
->HcdTailP
)
1822 if (TD
->OhciTransfer
== OhciTransfer
)
1837 if (TD
== OhciEndpoint
->HcdTailP
)
1844 OHCI_ProcessDoneIsoTD(OhciExtension
, PrevTD
, FALSE
);
1846 OHCI_ProcessDoneTD(OhciExtension
, PrevTD
, FALSE
);
1848 while (TD
->OhciTransfer
== OhciTransfer
);
1850 TmpTransfer
= LastTD
->OhciTransfer
;
1851 TmpTransfer
->NextTD
= TD
;
1853 LastTD
->NextHcdTD
= TD
;
1854 LastTD
->HwTD
.gTD
.NextTD
= TD
->PhysicalAddress
;
1859 *CompletedLength
= OhciTransfer
->TransferLen
;
1861 if (OhciTransfer
->TransferLen
)
1863 DPRINT("OHCI_AbortTransfer: *CompletedLength - %x\n", *CompletedLength
);
1869 OHCI_GetEndpointState(IN PVOID ohciExtension
,
1870 IN PVOID ohciEndpoint
)
1872 POHCI_ENDPOINT OhciEndpoint
= ohciEndpoint
;
1875 DPRINT_OHCI("OHCI_GetEndpointState: ... \n");
1877 ED
= OhciEndpoint
->HcdED
;
1879 if (ED
->Flags
& OHCI_HCD_TD_FLAG_NOT_ACCESSED
)
1880 return USBPORT_ENDPOINT_REMOVE
;
1882 if (ED
->HwED
.EndpointControl
.sKip
)
1883 return USBPORT_ENDPOINT_PAUSED
;
1885 return USBPORT_ENDPOINT_ACTIVE
;
1890 OHCI_RemoveEndpointFromSchedule(IN POHCI_ENDPOINT OhciEndpoint
)
1893 POHCI_HCD_ED PreviousED
;
1894 POHCI_STATIC_ED HeadED
;
1896 DPRINT_OHCI("OHCI_RemoveEndpointFromSchedule \n");
1898 ED
= OhciEndpoint
->HcdED
;
1899 HeadED
= OhciEndpoint
->HeadED
;
1901 if (&HeadED
->Link
== ED
->HcdEDLink
.Blink
)
1903 if (HeadED
->Type
== OHCI_STATIC_ED_TYPE_CONTROL
||
1904 HeadED
->Type
== OHCI_STATIC_ED_TYPE_BULK
)
1906 WRITE_REGISTER_ULONG(HeadED
->pNextED
, ED
->HwED
.NextED
);
1908 else if (HeadED
->Type
== OHCI_STATIC_ED_TYPE_INTERRUPT
)
1910 *HeadED
->pNextED
= ED
->HwED
.NextED
;
1914 DPRINT1("OHCI_RemoveEndpointFromSchedule: Unknown HeadED->Type - %x\n",
1921 PreviousED
= CONTAINING_RECORD(ED
->HcdEDLink
.Blink
,
1925 PreviousED
->HwED
.NextED
= ED
->HwED
.NextED
;
1928 RemoveEntryList(&ED
->HcdEDLink
);
1930 OhciEndpoint
->HeadED
= NULL
;
1935 OHCI_SetEndpointState(IN PVOID ohciExtension
,
1936 IN PVOID ohciEndpoint
,
1937 IN ULONG EndpointState
)
1939 POHCI_EXTENSION OhciExtension
= ohciExtension
;
1940 POHCI_ENDPOINT OhciEndpoint
= ohciEndpoint
;
1943 DPRINT_OHCI("OHCI_SetEndpointState: EndpointState - %x\n",
1946 ED
= OhciEndpoint
->HcdED
;
1948 switch (EndpointState
)
1950 case USBPORT_ENDPOINT_PAUSED
:
1951 ED
->HwED
.EndpointControl
.sKip
= 1;
1954 case USBPORT_ENDPOINT_ACTIVE
:
1955 ED
->HwED
.EndpointControl
.sKip
= 0;
1956 OHCI_EnableList(OhciExtension
, OhciEndpoint
);
1959 case USBPORT_ENDPOINT_REMOVE
:
1960 ED
->HwED
.EndpointControl
.sKip
= 1;
1961 ED
->Flags
|= OHCI_HCD_ED_FLAG_NOT_ACCESSED
;
1962 OHCI_RemoveEndpointFromSchedule(OhciEndpoint
);
1973 OHCI_PollAsyncEndpoint(IN POHCI_EXTENSION OhciExtension
,
1974 IN POHCI_ENDPOINT OhciEndpoint
)
1976 PUSBPORT_TRANSFER_PARAMETERS TransferParameters
;
1979 POHCI_HCD_TD NextTD
;
1981 PLIST_ENTRY DoneList
;
1982 POHCI_TRANSFER OhciTransfer
;
1983 POHCI_HCD_TD ControlStatusTD
;
1984 ULONG_PTR PhysicalAddress
;
1985 ULONG TransferNumber
;
1986 POHCI_TRANSFER transfer
;
1987 UCHAR ConditionCode
;
1988 BOOLEAN IsResetOnHalt
= FALSE
;
1990 //DPRINT_OHCI("OHCI_PollAsyncEndpoint: Endpoint - %p\n", OhciEndpoint);
1992 ED
= OhciEndpoint
->HcdED
;
1993 NextTdPA
= ED
->HwED
.HeadPointer
& OHCI_ED_HEAD_POINTER_MASK
;
2001 NextTD
= RegPacket
.UsbPortGetMappedVirtualAddress(NextTdPA
,
2004 DPRINT_OHCI("NextTD - %p\n", NextTD
);
2006 if ((ED
->HwED
.HeadPointer
& OHCI_ED_HEAD_POINTER_HALT
) == 0)
2007 goto ProcessListTDs
;
2011 IsResetOnHalt
= (ED
->Flags
& OHCI_HCD_ED_FLAG_RESET_ON_HALT
) != 0;
2012 DPRINT1("PollAsyncEndpoint: IsResetOnHalt %x\n", IsResetOnHalt
);
2014 for (TD
= OhciEndpoint
->HcdHeadP
; ; TD
= TD
->NextHcdTD
)
2024 DPRINT("TD == NextTD - %p\n", TD
);
2025 goto HandleDoneList
;
2028 OhciTransfer
= TD
->OhciTransfer
;
2029 ConditionCode
= TD
->HwTD
.gTD
.Control
.ConditionCode
;
2031 DPRINT("TD - %p, ConditionCode - %X\n", TD
, ConditionCode
);
2034 switch (ConditionCode
)
2036 case OHCI_TD_CONDITION_NO_ERROR
:
2037 TD
->Flags
|= OHCI_HCD_TD_FLAG_DONE
;
2038 InsertTailList(&OhciEndpoint
->TDList
, &TD
->DoneLink
);
2041 case OHCI_TD_CONDITION_NOT_ACCESSED
:
2042 TD
->Flags
|= (OHCI_HCD_TD_FLAG_DONE
| OHCI_HCD_TD_FLAG_NOT_ACCESSED
);
2043 InsertTailList(&OhciEndpoint
->TDList
, &TD
->DoneLink
);
2046 case OHCI_TD_CONDITION_DATA_UNDERRUN
:
2047 DPRINT1("DATA_UNDERRUN. Transfer->Flags - %X\n", OhciTransfer
->Flags
);
2049 if (OhciTransfer
->Flags
& OHCI_TRANSFER_FLAGS_SHORT_TRANSFER_OK
)
2051 IsResetOnHalt
= TRUE
;
2052 TD
->HwTD
.gTD
.Control
.ConditionCode
= OHCI_TD_CONDITION_NO_ERROR
;
2054 ControlStatusTD
= OhciTransfer
->ControlStatusTD
;
2056 if ((TD
->Flags
& OHCI_HCD_TD_FLAG_CONTROL_STATUS
) == 0 &&
2059 PhysicalAddress
= ControlStatusTD
->PhysicalAddress
;
2060 PhysicalAddress
|= (ED
->HwED
.HeadPointer
&
2061 OHCI_ED_HEAD_POINTER_FLAGS_MASK
);
2063 ED
->HwED
.HeadPointer
= PhysicalAddress
;
2065 NextTD
= OhciTransfer
->ControlStatusTD
;
2066 DPRINT("PhysicalAddress - %p, NextTD - %p\n", PhysicalAddress
, NextTD
);
2070 TransferParameters
= OhciTransfer
->TransferParameters
;
2072 if (TransferParameters
->IsTransferSplited
)
2074 TransferNumber
= TransferParameters
->TransferCounter
;
2075 transfer
= OhciTransfer
;
2079 transfer
= transfer
->NextTD
->OhciTransfer
;
2080 NextTD
= transfer
->NextTD
;
2082 while (transfer
&& TransferNumber
==
2083 transfer
->TransferParameters
->TransferCounter
);
2085 PhysicalAddress
= NextTD
->PhysicalAddress
;
2086 PhysicalAddress
|= (ED
->HwED
.HeadPointer
&
2087 OHCI_ED_HEAD_POINTER_FLAGS_MASK
);
2089 ED
->HwED
.HeadPointer
= PhysicalAddress
;
2090 DPRINT("PhysicalAddress - %p, NextTD - %p\n", PhysicalAddress
, NextTD
);
2094 PhysicalAddress
= OhciTransfer
->NextTD
->PhysicalAddress
;
2095 PhysicalAddress
|= (ED
->HwED
.HeadPointer
&
2096 OHCI_ED_HEAD_POINTER_FLAGS_MASK
);
2098 ED
->HwED
.HeadPointer
= PhysicalAddress
;
2100 NextTD
= OhciTransfer
->NextTD
;
2101 DPRINT("PhysicalAddress - %p, NextTD - %p\n", PhysicalAddress
, NextTD
);
2105 TD
->Flags
|= OHCI_HCD_TD_FLAG_DONE
;
2106 InsertTailList(&OhciEndpoint
->TDList
, &TD
->DoneLink
);
2113 TD
->Flags
|= OHCI_HCD_TD_FLAG_DONE
;
2114 InsertTailList(&OhciEndpoint
->TDList
, &TD
->DoneLink
);
2116 ED
->HwED
.HeadPointer
= OhciTransfer
->NextTD
->PhysicalAddress
|
2117 (ED
->HwED
.HeadPointer
&
2118 OHCI_ED_HEAD_POINTER_FLAGS_MASK
);
2120 NextTD
= OhciTransfer
->NextTD
;
2127 TD
= OhciEndpoint
->HcdHeadP
;
2129 while (TD
!= NextTD
)
2132 TD
->Flags
|= OHCI_HCD_TD_FLAG_DONE
;
2133 InsertTailList(&OhciEndpoint
->TDList
, &TD
->DoneLink
);
2140 OhciEndpoint
->HcdHeadP
= NextTD
;
2142 DoneList
= &OhciEndpoint
->TDList
;
2144 while (!IsListEmpty(DoneList
))
2146 TD
= CONTAINING_RECORD(DoneList
->Flink
,
2150 RemoveHeadList(DoneList
);
2152 if (TD
->Flags
& OHCI_HCD_TD_FLAG_DONE
&&
2153 TD
->Flags
& OHCI_HCD_TD_FLAG_PROCESSED
)
2155 OHCI_ProcessDoneTD(OhciExtension
, TD
, TRUE
);
2161 ED
->HwED
.HeadPointer
&= ~OHCI_ED_HEAD_POINTER_HALT
;
2162 DPRINT("ED->HwED.HeadPointer - %p\n", ED
->HwED
.HeadPointer
);
2168 OHCI_PollIsoEndpoint(IN POHCI_EXTENSION OhciExtension
,
2169 IN POHCI_ENDPOINT OhciEndpoint
)
2171 DPRINT1("OHCI_PollAsyncEndpoint: UNIMPLEMENTED. FIXME \n");
2177 OHCI_PollEndpoint(IN PVOID ohciExtension
,
2178 IN PVOID ohciEndpoint
)
2180 POHCI_EXTENSION OhciExtension
= ohciExtension
;
2181 POHCI_ENDPOINT OhciEndpoint
= ohciEndpoint
;
2184 DPRINT_OHCI("OHCI_PollEndpoint: OhciExtension - %p, Endpoint - %p\n",
2188 TransferType
= OhciEndpoint
->EndpointProperties
.TransferType
;
2190 if (TransferType
== USBPORT_TRANSFER_TYPE_ISOCHRONOUS
)
2192 OHCI_PollIsoEndpoint(OhciExtension
, OhciEndpoint
);
2196 if (TransferType
== USBPORT_TRANSFER_TYPE_CONTROL
||
2197 TransferType
== USBPORT_TRANSFER_TYPE_BULK
||
2198 TransferType
== USBPORT_TRANSFER_TYPE_INTERRUPT
)
2200 OHCI_PollAsyncEndpoint(OhciExtension
, OhciEndpoint
);
2206 OHCI_CheckController(IN PVOID ohciExtension
)
2208 POHCI_EXTENSION OhciExtension
= ohciExtension
;
2209 POHCI_OPERATIONAL_REGISTERS OperationalRegs
;
2210 PULONG HcControlReg
;
2211 OHCI_REG_CONTROL HcControl
;
2216 //DPRINT_OHCI("OHCI_CheckController: ...\n");
2218 OperationalRegs
= OhciExtension
->OperationalRegs
;
2220 if (!OHCI_HardwarePresent(OhciExtension
, TRUE
))
2223 HcControlReg
= (PULONG
)&OperationalRegs
->HcControl
;
2224 HcControl
.AsULONG
= READ_REGISTER_ULONG(HcControlReg
);
2226 if (HcControl
.HostControllerFunctionalState
!= OHCI_HC_STATE_OPERATIONAL
)
2229 FmNumber
= READ_REGISTER_ULONG(&OperationalRegs
->HcFmNumber
);
2230 FmDiff
= (USHORT
)(FmNumber
- OhciExtension
->HcdFmNumber
);
2232 if (FmNumber
== 0 || FmDiff
< 5)
2235 HcHCCA
= &OhciExtension
->HcResourcesVA
->HcHCCA
;
2236 OhciExtension
->HcdFmNumber
= FmNumber
;
2238 if (HcHCCA
->Pad1
== 0)
2240 HcHCCA
->Pad1
= 0xBAD1;
2244 DPRINT1("OHCI_CheckController: HcHCCA->Pad1 - %x\n", HcHCCA
->Pad1
);
2246 if (HcHCCA
->Pad1
== 0xBAD1)
2248 HcHCCA
->Pad1
= 0xBAD2;
2250 else if (HcHCCA
->Pad1
== 0xBAD2)
2252 HcHCCA
->Pad1
= 0xBAD3;
2254 RegPacket
.UsbPortInvalidateController(OhciExtension
,
2255 USBPORT_INVALIDATE_CONTROLLER_RESET
);
2261 OHCI_Get32BitFrameNumber(IN PVOID ohciExtension
)
2263 POHCI_EXTENSION OhciExtension
= ohciExtension
;
2268 HcHCCA
= &OhciExtension
->HcResourcesVA
->HcHCCA
;
2270 /* 5.4 FrameInterval Counter: Get32BitFrameNumber() */
2272 hp
= OhciExtension
->FrameHighPart
;
2273 fm
= HcHCCA
->FrameNumber
;
2275 DPRINT_OHCI("OHCI_Get32BitFrameNumber: hp - %lX, fm - %lX\n", hp
, fm
);
2277 return ((fm
& 0x7FFF) | hp
) + ((fm
^ hp
) & 0x8000);
2282 OHCI_InterruptNextSOF(IN PVOID ohciExtension
)
2284 POHCI_EXTENSION OhciExtension
= ohciExtension
;
2285 POHCI_OPERATIONAL_REGISTERS OperationalRegs
;
2286 PULONG InterruptEnableReg
;
2287 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable
;
2289 DPRINT_OHCI("OHCI_InterruptNextSOF: OhciExtension - %p\n",
2292 OperationalRegs
= OhciExtension
->OperationalRegs
;
2293 InterruptEnableReg
= (PULONG
)&OperationalRegs
->HcInterruptEnable
;
2295 /* Enable interrupt generation due to Start of Frame */
2296 IntEnable
.AsULONG
= 0;
2297 IntEnable
.StartofFrame
= 1;
2299 WRITE_REGISTER_ULONG(InterruptEnableReg
, IntEnable
.AsULONG
);
2304 OHCI_EnableInterrupts(IN PVOID ohciExtension
)
2306 POHCI_EXTENSION OhciExtension
= ohciExtension
;
2307 POHCI_OPERATIONAL_REGISTERS OperationalRegs
;
2308 PULONG InterruptEnableReg
;
2309 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable
;
2311 DPRINT_OHCI("OHCI_EnableInterrupts: OhciExtension - %p\n",
2314 OperationalRegs
= OhciExtension
->OperationalRegs
;
2315 InterruptEnableReg
= (PULONG
)&OperationalRegs
->HcInterruptEnable
;
2317 /* Enable interrupt generation */
2318 IntEnable
.AsULONG
= 0;
2319 IntEnable
.MasterInterruptEnable
= 1;
2321 WRITE_REGISTER_ULONG(InterruptEnableReg
, IntEnable
.AsULONG
);
2326 OHCI_DisableInterrupts(IN PVOID ohciExtension
)
2328 POHCI_EXTENSION OhciExtension
= ohciExtension
;
2329 POHCI_OPERATIONAL_REGISTERS OperationalRegs
;
2330 PULONG InterruptDisableReg
;
2331 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable
;
2333 DPRINT_OHCI("OHCI_DisableInterrupts\n");
2335 OperationalRegs
= OhciExtension
->OperationalRegs
;
2336 InterruptDisableReg
= (PULONG
)&OperationalRegs
->HcInterruptDisable
;
2338 /* Disable interrupt generation */
2339 IntDisable
.AsULONG
= 0;
2340 IntDisable
.MasterInterruptEnable
= 1;
2342 WRITE_REGISTER_ULONG(InterruptDisableReg
, IntDisable
.AsULONG
);
2347 OHCI_PollController(IN PVOID ohciExtension
)
2349 DPRINT1("OHCI_PollController: UNIMPLEMENTED. FIXME\n");
2354 OHCI_SetEndpointDataToggle(IN PVOID ohciExtension
,
2355 IN PVOID ohciEndpoint
,
2356 IN ULONG DataToggle
)
2358 POHCI_ENDPOINT OhciEndpoint
= ohciEndpoint
;
2361 DPRINT_OHCI("OHCI_SetEndpointDataToggle: Endpoint - %p, DataToggle - %x\n",
2365 ED
= OhciEndpoint
->HcdED
;
2368 ED
->HwED
.HeadPointer
|= OHCI_ED_HEAD_POINTER_CARRY
;
2370 ED
->HwED
.HeadPointer
&= ~OHCI_ED_HEAD_POINTER_CARRY
;
2375 OHCI_GetEndpointStatus(IN PVOID ohciExtension
,
2376 IN PVOID ohciEndpoint
)
2378 POHCI_ENDPOINT OhciEndpoint
= ohciEndpoint
;
2380 ULONG EndpointStatus
= USBPORT_ENDPOINT_RUN
;
2382 DPRINT_OHCI("OHCI_GetEndpointStatus: ... \n");
2384 ED
= OhciEndpoint
->HcdED
;
2386 if ((ED
->HwED
.HeadPointer
& OHCI_ED_HEAD_POINTER_HALT
) &&
2387 !(ED
->Flags
& OHCI_HCD_ED_FLAG_RESET_ON_HALT
))
2389 EndpointStatus
= USBPORT_ENDPOINT_HALT
;
2392 return EndpointStatus
;
2397 OHCI_SetEndpointStatus(IN PVOID ohciExtension
,
2398 IN PVOID ohciEndpoint
,
2399 IN ULONG EndpointStatus
)
2401 POHCI_EXTENSION OhciExtension
= ohciExtension
;
2402 POHCI_ENDPOINT OhciEndpoint
= ohciEndpoint
;
2405 DPRINT_OHCI("OHCI_SetEndpointStatus: Endpoint - %p, EndpointStatus - %lX\n",
2409 if (EndpointStatus
== USBPORT_ENDPOINT_RUN
)
2411 ED
= OhciEndpoint
->HcdED
;
2412 ED
->HwED
.HeadPointer
&= ~OHCI_ED_HEAD_POINTER_HALT
;
2414 OHCI_EnableList(OhciExtension
, OhciEndpoint
);
2416 else if (EndpointStatus
== USBPORT_ENDPOINT_HALT
)
2424 OHCI_ResetController(IN PVOID ohciExtension
)
2426 POHCI_EXTENSION OhciExtension
= ohciExtension
;
2427 POHCI_OPERATIONAL_REGISTERS OperationalRegs
;
2430 PULONG CommandStatusReg
;
2431 PULONG InterruptEnableReg
;
2432 PULONG FmIntervalReg
;
2434 PULONG PortStatusReg
;
2435 OHCI_REG_CONTROL ControlBak
;
2436 OHCI_REG_CONTROL Control
;
2437 OHCI_REG_COMMAND_STATUS CommandStatus
;
2438 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable
;
2440 ULONG_PTR ControlHeadED
;
2441 ULONG_PTR BulkHeadED
;
2442 OHCI_REG_FRAME_INTERVAL FrameInterval
;
2443 ULONG_PTR PeriodicStart
;
2444 ULONG_PTR LSThreshold
;
2445 OHCI_REG_RH_STATUS RhStatus
;
2446 OHCI_REG_RH_DESCRIPTORA RhDescriptorA
;
2447 OHCI_REG_RH_PORT_STATUS PortStatus
;
2451 DPRINT("OHCI_ResetController: ... \n");
2453 OperationalRegs
= OhciExtension
->OperationalRegs
;
2455 ControlReg
= (PULONG
)&OperationalRegs
->HcControl
;
2456 CommandStatusReg
= (PULONG
)&OperationalRegs
->HcCommandStatus
;
2457 InterruptEnableReg
= (PULONG
)&OperationalRegs
->HcInterruptEnable
;
2458 FmIntervalReg
= (PULONG
)&OperationalRegs
->HcFmInterval
;
2459 RhStatusReg
= (PULONG
)&OperationalRegs
->HcRhStatus
;
2461 /* Backup FrameNumber from HcHCCA */
2462 FrameNumber
= OhciExtension
->HcResourcesVA
->HcHCCA
.FrameNumber
;
2464 /* Backup registers */
2465 ControlBak
.AsULONG
= READ_REGISTER_ULONG(ControlReg
);
2466 HCCA
= READ_REGISTER_ULONG(&OperationalRegs
->HcHCCA
);
2467 ControlHeadED
= READ_REGISTER_ULONG(&OperationalRegs
->HcControlHeadED
);
2468 BulkHeadED
= READ_REGISTER_ULONG(&OperationalRegs
->HcBulkHeadED
);
2469 FrameInterval
.AsULONG
= READ_REGISTER_ULONG(FmIntervalReg
);
2470 PeriodicStart
= READ_REGISTER_ULONG(&OperationalRegs
->HcPeriodicStart
);
2471 LSThreshold
= READ_REGISTER_ULONG(&OperationalRegs
->HcLSThreshold
);
2473 /* Reset HostController */
2474 CommandStatus
.AsULONG
= 0;
2475 CommandStatus
.HostControllerReset
= 1;
2476 WRITE_REGISTER_ULONG(CommandStatusReg
, CommandStatus
.AsULONG
);
2478 KeStallExecutionProcessor(10);
2480 /* Restore registers */
2481 WRITE_REGISTER_ULONG(&OperationalRegs
->HcHCCA
, HCCA
);
2482 WRITE_REGISTER_ULONG(&OperationalRegs
->HcControlHeadED
, ControlHeadED
);
2483 WRITE_REGISTER_ULONG(&OperationalRegs
->HcBulkHeadED
, BulkHeadED
);
2485 /* Set OPERATIONAL state for HC */
2486 Control
.AsULONG
= 0;
2487 Control
.HostControllerFunctionalState
= OHCI_HC_STATE_OPERATIONAL
;
2488 WRITE_REGISTER_ULONG(ControlReg
, Control
.AsULONG
);
2490 /* Set Toggle bit for FmInterval register */
2491 FrameInterval
.FrameIntervalToggle
= 1;
2492 WRITE_REGISTER_ULONG(FmIntervalReg
, FrameInterval
.AsULONG
);
2494 /* Restore registers */
2495 WRITE_REGISTER_ULONG(&OperationalRegs
->HcFmNumber
, FrameNumber
);
2496 WRITE_REGISTER_ULONG(&OperationalRegs
->HcPeriodicStart
, PeriodicStart
);
2497 WRITE_REGISTER_ULONG(&OperationalRegs
->HcLSThreshold
, LSThreshold
);
2499 /* Setup RhStatus register */
2500 RhStatus
.AsULONG
= 0;
2501 RhStatus
.SetRemoteWakeupEnable
= 1;
2502 RhStatus
.SetGlobalPower
= 1;
2503 WRITE_REGISTER_ULONG(RhStatusReg
, RhStatus
.AsULONG
);
2505 /* Setup RH PortStatus registers */
2506 RhDescriptorA
= OHCI_ReadRhDescriptorA(OhciExtension
);
2507 NumPorts
= RhDescriptorA
.NumberDownstreamPorts
;
2509 PortStatus
.AsULONG
= 0;
2510 PortStatus
.SetPortPower
= 1;
2512 for (ix
= 0; ix
< NumPorts
; ix
++)
2514 PortStatusReg
= (PULONG
)&OperationalRegs
->HcRhPortStatus
[ix
];
2515 WRITE_REGISTER_ULONG(PortStatusReg
, PortStatus
.AsULONG
);
2518 /* Restore HcControl register */
2519 ControlBak
.HostControllerFunctionalState
= OHCI_HC_STATE_OPERATIONAL
;
2520 WRITE_REGISTER_ULONG(ControlReg
, ControlBak
.AsULONG
);
2522 /* Setup HcInterruptEnable register */
2523 IntEnable
.AsULONG
= 0xFFFFFFFF;
2524 IntEnable
.Reserved1
= 0;
2525 WRITE_REGISTER_ULONG(InterruptEnableReg
, IntEnable
.AsULONG
);
2530 OHCI_StartSendOnePacket(IN PVOID ohciExtension
,
2531 IN PVOID PacketParameters
,
2533 IN PULONG pDataLength
,
2536 IN ULONG BufferLength
,
2537 IN USBD_STATUS
* pUSBDStatus
)
2539 DPRINT1("OHCI_StartSendOnePacket: UNIMPLEMENTED. FIXME\n");
2540 return MP_STATUS_SUCCESS
;
2545 OHCI_EndSendOnePacket(IN PVOID ohciExtension
,
2546 IN PVOID PacketParameters
,
2548 IN PULONG pDataLength
,
2551 IN ULONG BufferLength
,
2552 IN USBD_STATUS
* pUSBDStatus
)
2554 DPRINT1("OHCI_EndSendOnePacket: UNIMPLEMENTED. FIXME\n");
2555 return MP_STATUS_SUCCESS
;
2560 OHCI_PassThru(IN PVOID ohciExtension
,
2561 IN PVOID passThruParameters
,
2562 IN ULONG ParameterLength
,
2563 IN PVOID pParameters
)
2565 DPRINT1("OHCI_PassThru: UNIMPLEMENTED. FIXME\n");
2566 return MP_STATUS_SUCCESS
;
2571 OHCI_Unload(IN PDRIVER_OBJECT DriverObject
)
2574 DPRINT1("OHCI_Unload: Not supported\n");
2581 OHCI_FlushInterrupts(IN PVOID uhciExtension
)
2584 DPRINT1("OHCI_FlushInterrupts: Not supported\n");
2591 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
2592 IN PUNICODE_STRING RegistryPath
)
2596 DPRINT_OHCI("DriverEntry: DriverObject - %p, RegistryPath - %wZ\n",
2600 RtlZeroMemory(&RegPacket
, sizeof(USBPORT_REGISTRATION_PACKET
));
2602 RegPacket
.MiniPortVersion
= USB_MINIPORT_VERSION_OHCI
;
2604 RegPacket
.MiniPortFlags
= USB_MINIPORT_FLAGS_INTERRUPT
|
2605 USB_MINIPORT_FLAGS_MEMORY_IO
;
2607 RegPacket
.MiniPortBusBandwidth
= TOTAL_USB11_BUS_BANDWIDTH
;
2609 RegPacket
.MiniPortExtensionSize
= sizeof(OHCI_EXTENSION
);
2610 RegPacket
.MiniPortEndpointSize
= sizeof(OHCI_ENDPOINT
);
2611 RegPacket
.MiniPortTransferSize
= sizeof(OHCI_TRANSFER
);
2612 RegPacket
.MiniPortResourcesSize
= sizeof(OHCI_HC_RESOURCES
);
2614 RegPacket
.OpenEndpoint
= OHCI_OpenEndpoint
;
2615 RegPacket
.ReopenEndpoint
= OHCI_ReopenEndpoint
;
2616 RegPacket
.QueryEndpointRequirements
= OHCI_QueryEndpointRequirements
;
2617 RegPacket
.CloseEndpoint
= OHCI_CloseEndpoint
;
2618 RegPacket
.StartController
= OHCI_StartController
;
2619 RegPacket
.StopController
= OHCI_StopController
;
2620 RegPacket
.SuspendController
= OHCI_SuspendController
;
2621 RegPacket
.ResumeController
= OHCI_ResumeController
;
2622 RegPacket
.InterruptService
= OHCI_InterruptService
;
2623 RegPacket
.InterruptDpc
= OHCI_InterruptDpc
;
2624 RegPacket
.SubmitTransfer
= OHCI_SubmitTransfer
;
2625 RegPacket
.SubmitIsoTransfer
= OHCI_SubmitIsoTransfer
;
2626 RegPacket
.AbortTransfer
= OHCI_AbortTransfer
;
2627 RegPacket
.GetEndpointState
= OHCI_GetEndpointState
;
2628 RegPacket
.SetEndpointState
= OHCI_SetEndpointState
;
2629 RegPacket
.PollEndpoint
= OHCI_PollEndpoint
;
2630 RegPacket
.CheckController
= OHCI_CheckController
;
2631 RegPacket
.Get32BitFrameNumber
= OHCI_Get32BitFrameNumber
;
2632 RegPacket
.InterruptNextSOF
= OHCI_InterruptNextSOF
;
2633 RegPacket
.EnableInterrupts
= OHCI_EnableInterrupts
;
2634 RegPacket
.DisableInterrupts
= OHCI_DisableInterrupts
;
2635 RegPacket
.PollController
= OHCI_PollController
;
2636 RegPacket
.SetEndpointDataToggle
= OHCI_SetEndpointDataToggle
;
2637 RegPacket
.GetEndpointStatus
= OHCI_GetEndpointStatus
;
2638 RegPacket
.SetEndpointStatus
= OHCI_SetEndpointStatus
;
2639 RegPacket
.ResetController
= OHCI_ResetController
;
2640 RegPacket
.RH_GetRootHubData
= OHCI_RH_GetRootHubData
;
2641 RegPacket
.RH_GetStatus
= OHCI_RH_GetStatus
;
2642 RegPacket
.RH_GetPortStatus
= OHCI_RH_GetPortStatus
;
2643 RegPacket
.RH_GetHubStatus
= OHCI_RH_GetHubStatus
;
2644 RegPacket
.RH_SetFeaturePortReset
= OHCI_RH_SetFeaturePortReset
;
2645 RegPacket
.RH_SetFeaturePortPower
= OHCI_RH_SetFeaturePortPower
;
2646 RegPacket
.RH_SetFeaturePortEnable
= OHCI_RH_SetFeaturePortEnable
;
2647 RegPacket
.RH_SetFeaturePortSuspend
= OHCI_RH_SetFeaturePortSuspend
;
2648 RegPacket
.RH_ClearFeaturePortEnable
= OHCI_RH_ClearFeaturePortEnable
;
2649 RegPacket
.RH_ClearFeaturePortPower
= OHCI_RH_ClearFeaturePortPower
;
2650 RegPacket
.RH_ClearFeaturePortSuspend
= OHCI_RH_ClearFeaturePortSuspend
;
2651 RegPacket
.RH_ClearFeaturePortEnableChange
= OHCI_RH_ClearFeaturePortEnableChange
;
2652 RegPacket
.RH_ClearFeaturePortConnectChange
= OHCI_RH_ClearFeaturePortConnectChange
;
2653 RegPacket
.RH_ClearFeaturePortResetChange
= OHCI_RH_ClearFeaturePortResetChange
;
2654 RegPacket
.RH_ClearFeaturePortSuspendChange
= OHCI_RH_ClearFeaturePortSuspendChange
;
2655 RegPacket
.RH_ClearFeaturePortOvercurrentChange
= OHCI_RH_ClearFeaturePortOvercurrentChange
;
2656 RegPacket
.RH_DisableIrq
= OHCI_RH_DisableIrq
;
2657 RegPacket
.RH_EnableIrq
= OHCI_RH_EnableIrq
;
2658 RegPacket
.StartSendOnePacket
= OHCI_StartSendOnePacket
;
2659 RegPacket
.EndSendOnePacket
= OHCI_EndSendOnePacket
;
2660 RegPacket
.PassThru
= OHCI_PassThru
;
2661 RegPacket
.FlushInterrupts
= OHCI_FlushInterrupts
;
2663 DriverObject
->DriverUnload
= OHCI_Unload
;
2665 Status
= USBPORT_RegisterUSBPortDriver(DriverObject
,
2666 USB10_MINIPORT_INTERFACE_VERSION
,
2669 DPRINT_OHCI("DriverEntry: USBPORT_RegisterUSBPortDriver return Status - %x\n",