Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[USBUHCI_NEW] Bring-in the USB UHCI miniport driver created by Vadim Galyant. #245

Merged
merged 120 commits into from Sep 1, 2018

Conversation

AmineKhaldi
Copy link
Member

No description provided.

};
USHORT AsUSHORT;
} UHCI_PCI_LEGSUP;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file could use some C_ASSERTs

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

@HBelusca
Copy link
Contributor

Can we wait for few days until I'm able to finish to review this PR? :)

IN PUSHORT Status)
{
DPRINT("UhciRHGetStatus: ...\n");
*Status = 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Magic.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Constantify.

VOID
NTAPI
UhciRHGetRootHubData(IN PVOID uhciExtension,
IN PVOID rootHubData)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function should use PUSBPORT_ROOT_HUB_DATA directly. I'll push a change to fix this in usbport and usbohci shortly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will fix this at the last minute or after fixes in usbport, so that the builder does not give errors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. Let me know if you want me to get something into master before this is merged.

//DPRINT("UhciRHGetPortStatus: ...\n");

BaseRegister = UhciExtension->BaseRegister;
PortControlRegister = &BaseRegister->PortControl[Port-1].AsUSHORT;
Copy link
Member

@ThFabba ThFabba Jan 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll want a Port > 0 assert again here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

portStatus.Suspend = FALSE;
}

// FIXME HcFlavor in usbport
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds fixable :p

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First we need HcFlavor support in usbport.
This is for VIA controllers.

//if (UhciExtension->HcFlavor == UHCI_Piix4)
if (TRUE)
{
portStatus.OverCurrent = PortControl.Reserved2 & 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Magic

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intel use it bits, but not documented in UHCI 1.1 spec.

portStatus.CurrentConnectStatus = PortControl.CurrentConnectStatus;
portStatus.PortEnabledDisabled = PortControl.PortEnabledDisabled;

if (PortControl.Suspend == TRUE &&
Copy link
Member

@ThFabba ThFabba Jan 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we generally use 0/1 rather than FALSE/TRUE for bitfields.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed

portStatus.LowSpeedDeviceAttached = PortControl.LowSpeedDevice;
portChange.ConnectStatusChange = PortControl.ConnectStatusChange;

port = 1 << (Port - 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

portBit or something would be more descriptive.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ranamed

DPRINT("UhciRHPortResetComplete: ...\n");

BaseRegister = UhciExtension->BaseRegister;
Port = *(PUSHORT)pPort - 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ASSERT, possibly with another added variable to avoid all the casting

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Port = *(PUSHORT)pPort;
ASSERT(Port != 0);
PortControlRegister = &BaseRegister->PortControl[Port - 1].AsUSHORT;

{
continue;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can stop the while loop here, since all the paths below use return, so will never loop.
E.g.:

while (UhciHardwarePresent(UhciExtension))
{
    PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
    if (PortControl.PortReset == 0)
    {
        break;
    }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed

DPRINT("UhciRHSetFeaturePortReset: ...\n");

ResetPortMask = UhciExtension->ResetPortMask;
port = 1 << (Port - 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

portBit or similar

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ranamed

@ThFabba
Copy link
Member

ThFabba commented Jan 12, 2018

I've only just started, so yes.


VOID
NTAPI
UhciRHSetFeaturePortResetWorker(IN PUHCI_EXTENSION UhciExtension,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious why this is its own function. It only seems to be called in once place.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It use also UhciVia...(), but it not implemented.

PortControlRegister = (PUSHORT)&BaseRegister->PortControl[Port - 1];
PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);

if (PortControl.ConnectStatusChange == TRUE)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you check whether the bit is set here, but not in UhciRHClearFeaturePortEnableChange?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it need to be checked in UhciRHClearFeaturePortEnableChange?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it need to be checked here? My point is that these two functions basically do the same thing, just with different bits. So it seems odd that one has the check and one does not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes no sense to do a check in UhciRHClearFeaturePortEnableChange(). For UhciRHClearFeaturePortEnableChange() such a case is possible when we call USBH_SyncClearPortStatus() in USBH_StartHubFdoDevice().

NTAPI
UhciRHDisableIrq(IN PVOID uhciExtension)
{
//DPRINT("UhciRHDisableIrq: \n");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought these were pretty important. Is UHCI special in that it doesn't need them?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleted.

while (TD)
{
TD->HwTD.Token.DataToggle = (TD->HwTD.Token.DataToggle == FALSE);
DataToggle = (DataToggle == FALSE);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DataToggle = !DataToggle; seems more intuitive to me but YMMV

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, you variant looks easier.

UHCI_TD HwTD;
/* Software */
USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
ULONG_PTR PhysicalAddress;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing this structure doesn't change its size depending on whether you run a 32 or 64 bit OS. If it's always 32 bits, ULONG is the right choice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Earlier I already got rid of ULONG_PTR, but sent a commit to the "usb_wip" branch. By the way, in usbport there are also several changes. I will work on this after the "Usbport transaction translator" so as not to get confused.


if (InterlockedIncrement(&UhciExtension->LockFrameList) != 1)
{
InterlockedDecrement(&UhciExtension->LockFrameList);
Copy link
Member

@ThFabba ThFabba Jan 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This lock seems odd. It protects code rather than data, which is a red flag.
If a second thread can get here and bail out while the first thread is already done walking the list but hasn't released the lock yet, the second cleanup would do nothing, even though there may be work to be done. Is this acceptable for this function (i.e. it just needs a "best effort" approach)? That might deserve a comment if so.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is clearing the list for isochronous transfers. This is also not implemented yet, so it may look strange. I can make them as a comment, so as not to forget about them. Or?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment sounds fine to me.

NewFrameNumber = UhciGet32BitFrameNumber(UhciExtension);
OldFrameNumber = UhciExtension->FrameNumber;

if ((NewFrameNumber - OldFrameNumber) < UHCI_FRAME_LIST_MAX_ENTRIES &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do frame numbers roll over or are they monotonously increasing? If the former, you may get an integer overflow here; if the latter, ASSERT(NewFrameNumber >= OldFrameNumber) above

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in theory there may be an overflow here. Since MAX_ULONG == 0xFFFFFFFF == 4,294,967,295, and in NewFrameNumber are stored milliseconds (1 USB frame == 1 millisecond), then dividing by 1000 we get ~ 4,294,967 seconds. Dividing by (60 * 60 * 24), we get ~ 50 days. Thus, approximately 50 days after switching on the computer, we can lose isochronous transmissions (usually an audio signal).

@@ -772,6 +773,8 @@ UhciStopController(IN PVOID uhciExtension,
DbgBreakPoint();
break;
}

Command.AsUSHORT = READ_PORT_USHORT(CommandReg);
}
Copy link
Contributor

@vgalnt vgalnt Jan 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a slightly different variant:
-- while (((UHCI_USB_COMMAND)READ_PORT_USHORT(CommandReg)).HcReset == 1)
++ while (Command.AsUSHORT = READ_PORT_USHORT(CommandReg),
++ Command.HcReset == 1)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to overwrite mine, I just wanted to have the build green.


#define UHCI_ENDPOINT_FLAG_HALTED 1
#define UHCI_ENDPOINT_FLAG_RESERVED 2
#define UHCI_ENDPOINT_FLAG_CONTROLL_OR_ISO 4
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

control*

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

IN PUSBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements)
{
ULONG TransferType;
ULONG TdCont;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TdCount*

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

{
DPRINT1("UhciTakeControlHC: MP_STATUS_ERROR\n");
MpStatus = MP_STATUS_ERROR;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the function return here? Is there other error handling missing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. Here it should be. It ok.

HcStatus.AsUSHORT = READ_PORT_USHORT(StatusRegister);
DPRINT("UhciTakeControlHC: HcStatus.AsUSHORT - %04X\n", HcStatus.AsUSHORT);

if (HcStatus.HcHalted == 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while (HcStatus.HcHalted == 0) ... if (CurrentTime ...) break; seems more intuitive than if-do-while.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed

@@ -81,7 +81,7 @@ UhciCleanupFrameListEntry(IN PUHCI_EXTENSION UhciExtension,
IN ULONG Index)
{
PUHCI_HC_RESOURCES UhciResources;
ULONG_PTR PhysicalAddress;
ULONG PhysicalAddress;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah? so the physical address can never be greater than 0xffffffff ? Or should one use ULONGLONG instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, all these controller types only support 32 bit DMA.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment in HalAllocateCommonBuffer() - is called from USBPORT_AllocateCommonBuffer().

@@ -34,6 +34,7 @@ extern USBPORT_REGISTRATION_PACKET RegPacket;
typedef struct _UHCI_ENDPOINT *PUHCI_ENDPOINT;
typedef struct _UHCI_TRANSFER *PUHCI_TRANSFER;

#if !defined(_M_X64)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it possible to have the #if !defined (_M_X64) for the new/modified fields inside the structure itself?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_M_X64 is not a thing by the way. There's _M_IX86 and _M_AMD64

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took _M_X64 because it is already used in usbport.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, _M_X64 is actually a synonym, I didn't know that. This is okay then.

@@ -291,30 +291,31 @@ UhciQueryEndpointRequirements(IN PVOID uhciExtension,
TdCount = 2 * UHCI_MAX_ISO_TD_COUNT;

EndpointRequirements->HeaderBufferSize = 0 + // Iso queue is have not Queue Heads
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"is have not..." --> "does not have ..."

ULONG PhysicalAddress;
ULONG Flags;
struct _UHCI_HCD_TD * NextHcdTD;
_ANONYMOUS_UNION union {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can move the #if !defined (M_X64) inside just for this union, and the ULONG Padded[x]; that is after.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I chahged. It turned out very human-readable (how do you like) :).
Btw, I fixed ULONG Padded[15] instead ULONG Padded[9], thank you.


#define UHCI_FRAME_LIST_POINTER_VALID (0 << 0)
#define UHCI_FRAME_LIST_POINTER_TERMINATE (1 << 0)
#define UHCI_FRAME_LIST_POINTER_TD (0 << 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand what "0 << 1" should do: isn't it equal to 0 ?

Copy link
Member

@ThFabba ThFabba Jan 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It means "bit 1 has the value 0", to contrast with (1 << 1). So yes it's 0, but it's an annotated 0 :p

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kl


for (ix = 0; ix < 10; ++ix)
{
KeStallExecutionProcessor(50);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a general question for me to understand something: calling KeStallExecutionProcessor (that really stalls the CPU) instead of just calling e.g. KeDelayExecutionThread, is to be very sure that nobody else could mess with values in IO ports?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's generally used for short waits, either because you're at a high IRQL and can't invoke the scheduler, or to avoid the scheduling overhead (your next timeslice may come in several ms, i.e. much much later than 50µs)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Callers of KeDelayExecutionThread must be running at IRQL <= APC_LEVEL.
Callers of KeStallExecutionProcessor can be running at any IRQL.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the info!

BaseRegister = UhciExtension->BaseRegister;

Port = *(PUSHORT)pPort;
ASSERT(Port);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like port numbers are 1-based. Is it so because of the specifications? Or is it because in your code port number "0" has a special meaning?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We using bitmask (UhciExtension->ResetPortMask,...)
And in specifications use port - requests with "The port number must be a valid port number for that hub, greater than zero."

NTAPI
UhciRHDisableIrq(IN PVOID uhciExtension)
{
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not implemented? Or should this function do nothing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This 2 functions for UHCI not used (do nothing).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Maybe you can add a comment in the code to say it's on purpose?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@ThFabba ThFabba merged commit a1a65e9 into reactos:master Sep 1, 2018
@HBelusca HBelusca removed the review pending For PRs undergoing review. label Jan 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement For PRs with an enhancement/new feature.
Projects
None yet