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
Conversation
06ff876
to
af43913
Compare
}; | ||
USHORT AsUSHORT; | ||
} UHCI_PCI_LEGSUP; | ||
|
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
Can we wait for few days until I'm able to finish to review this PR? :) |
drivers/usb/usbuhci_new/roothub.c
Outdated
IN PUSHORT Status) | ||
{ | ||
DPRINT("UhciRHGetStatus: ...\n"); | ||
*Status = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Magic.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
drivers/usb/usbuhci_new/roothub.c
Outdated
//DPRINT("UhciRHGetPortStatus: ...\n"); | ||
|
||
BaseRegister = UhciExtension->BaseRegister; | ||
PortControlRegister = &BaseRegister->PortControl[Port-1].AsUSHORT; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
drivers/usb/usbuhci_new/roothub.c
Outdated
portStatus.Suspend = FALSE; | ||
} | ||
|
||
// FIXME HcFlavor in usbport |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds fixable :p
There was a problem hiding this comment.
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.
drivers/usb/usbuhci_new/roothub.c
Outdated
//if (UhciExtension->HcFlavor == UHCI_Piix4) | ||
if (TRUE) | ||
{ | ||
portStatus.OverCurrent = PortControl.Reserved2 & 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Magic
There was a problem hiding this comment.
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.
drivers/usb/usbuhci_new/roothub.c
Outdated
portStatus.CurrentConnectStatus = PortControl.CurrentConnectStatus; | ||
portStatus.PortEnabledDisabled = PortControl.PortEnabledDisabled; | ||
|
||
if (PortControl.Suspend == TRUE && |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed
drivers/usb/usbuhci_new/roothub.c
Outdated
portStatus.LowSpeedDeviceAttached = PortControl.LowSpeedDevice; | ||
portChange.ConnectStatusChange = PortControl.ConnectStatusChange; | ||
|
||
port = 1 << (Port - 1); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ranamed
drivers/usb/usbuhci_new/roothub.c
Outdated
DPRINT("UhciRHPortResetComplete: ...\n"); | ||
|
||
BaseRegister = UhciExtension->BaseRegister; | ||
Port = *(PUSHORT)pPort - 1; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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;
drivers/usb/usbuhci_new/roothub.c
Outdated
{ | ||
continue; | ||
} | ||
|
There was a problem hiding this comment.
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;
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed
drivers/usb/usbuhci_new/roothub.c
Outdated
DPRINT("UhciRHSetFeaturePortReset: ...\n"); | ||
|
||
ResetPortMask = UhciExtension->ResetPortMask; | ||
port = 1 << (Port - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
portBit or similar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ranamed
I've only just started, so yes. |
|
||
VOID | ||
NTAPI | ||
UhciRHSetFeaturePortResetWorker(IN PUHCI_EXTENSION UhciExtension, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
drivers/usb/usbuhci_new/roothub.c
Outdated
PortControlRegister = (PUSHORT)&BaseRegister->PortControl[Port - 1]; | ||
PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister); | ||
|
||
if (PortControl.ConnectStatusChange == TRUE) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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().
drivers/usb/usbuhci_new/roothub.c
Outdated
NTAPI | ||
UhciRHDisableIrq(IN PVOID uhciExtension) | ||
{ | ||
//DPRINT("UhciRHDisableIrq: \n"); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deleted.
drivers/usb/usbuhci_new/usbuhci.c
Outdated
while (TD) | ||
{ | ||
TD->HwTD.Token.DataToggle = (TD->HwTD.Token.DataToggle == FALSE); | ||
DataToggle = (DataToggle == FALSE); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
drivers/usb/usbuhci_new/usbuhci.h
Outdated
UHCI_TD HwTD; | ||
/* Software */ | ||
USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket; | ||
ULONG_PTR PhysicalAddress; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
drivers/usb/usbuhci_new/usbuhci.c
Outdated
|
||
if (InterlockedIncrement(&UhciExtension->LockFrameList) != 1) | ||
{ | ||
InterlockedDecrement(&UhciExtension->LockFrameList); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 && |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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).
drivers/usb/usbuhci_new/usbuhci.c
Outdated
@@ -772,6 +773,8 @@ UhciStopController(IN PVOID uhciExtension, | |||
DbgBreakPoint(); | |||
break; | |||
} | |||
|
|||
Command.AsUSHORT = READ_PORT_USHORT(CommandReg); | |||
} |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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.
drivers/usb/usbuhci_new/usbuhci.h
Outdated
|
||
#define UHCI_ENDPOINT_FLAG_HALTED 1 | ||
#define UHCI_ENDPOINT_FLAG_RESERVED 2 | ||
#define UHCI_ENDPOINT_FLAG_CONTROLL_OR_ISO 4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
control*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
drivers/usb/usbuhci_new/usbuhci.c
Outdated
IN PUSBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements) | ||
{ | ||
ULONG TransferType; | ||
ULONG TdCont; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TdCount*
There was a problem hiding this comment.
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; | ||
} |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
drivers/usb/usbuhci_new/usbuhci.c
Outdated
HcStatus.AsUSHORT = READ_PORT_USHORT(StatusRegister); | ||
DPRINT("UhciTakeControlHC: HcStatus.AsUSHORT - %04X\n", HcStatus.AsUSHORT); | ||
|
||
if (HcStatus.HcHalted == 0) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed
drivers/usb/usbuhci_new/usbuhci.c
Outdated
@@ -81,7 +81,7 @@ UhciCleanupFrameListEntry(IN PUHCI_EXTENSION UhciExtension, | |||
IN ULONG Index) | |||
{ | |||
PUHCI_HC_RESOURCES UhciResources; | |||
ULONG_PTR PhysicalAddress; | |||
ULONG PhysicalAddress; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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().
drivers/usb/usbuhci_new/usbuhci.h
Outdated
@@ -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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
drivers/usb/usbuhci_new/usbuhci.c
Outdated
@@ -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 |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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 ?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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."
drivers/usb/usbuhci_new/roothub.c
Outdated
NTAPI | ||
UhciRHDisableIrq(IN PVOID uhciExtension) | ||
{ | ||
return; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
…ListEntry() with correct.
No description provided.