ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Ros-diffs
September 2018
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
24 participants
223 discussions
Start a n
N
ew thread
03/03: [WINLOGON] On logoff, also disconnect from any remote location
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=cbff9a30461c71e408468…
commit cbff9a30461c71e408468a54353775266ebb1314 Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Tue Sep 11 08:15:37 2018 +0200 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Tue Sep 11 08:30:31 2018 +0200 [WINLOGON] On logoff, also disconnect from any remote location This avoids keeping connections open and reopening them as soon as the user reopens their session. This fixes network shared being duplicated each time session is reopened. CORE-15012 --- base/system/winlogon/CMakeLists.txt | 2 +- base/system/winlogon/sas.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/base/system/winlogon/CMakeLists.txt b/base/system/winlogon/CMakeLists.txt index 8610bbfc91..64d3fef8b5 100644 --- a/base/system/winlogon/CMakeLists.txt +++ b/base/system/winlogon/CMakeLists.txt @@ -22,6 +22,6 @@ add_rc_deps(winlogon.rc ${CMAKE_CURRENT_SOURCE_DIR}/res/winlogon.ico) add_executable(winlogon ${SOURCE} winlogon.rc) target_link_libraries(winlogon wine) set_module_type(winlogon win32gui) -add_importlibs(winlogon user32 advapi32 userenv secur32 rpcrt4 msvcrt kernel32 ntdll) +add_importlibs(winlogon user32 advapi32 userenv secur32 rpcrt4 mpr msvcrt kernel32 ntdll) add_pch(winlogon winlogon.h SOURCE) add_cd_file(TARGET winlogon DESTINATION reactos/system32 FOR all) diff --git a/base/system/winlogon/sas.c b/base/system/winlogon/sas.c index e56ba639e7..d914bebefc 100644 --- a/base/system/winlogon/sas.c +++ b/base/system/winlogon/sas.c @@ -657,6 +657,9 @@ LogoffShutdownThread( ret = 0; } + /* Cancel all the user connections */ + WNetClearConnections(0); + if (LSData->Session->UserToken) RevertToSelf();
6 years, 3 months
1
0
0
0
02/03: [SDK] Add WNetClearConnections() in the headers for undocumented stuff
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6f5da265c87c32524db45…
commit 6f5da265c87c32524db4557a86a5d27815538aa3 Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Tue Sep 11 08:14:50 2018 +0200 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Tue Sep 11 08:30:31 2018 +0200 [SDK] Add WNetClearConnections() in the headers for undocumented stuff CORE-15012 --- sdk/include/reactos/undocuser.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sdk/include/reactos/undocuser.h b/sdk/include/reactos/undocuser.h index 5e2074a217..aadeb667b9 100644 --- a/sdk/include/reactos/undocuser.h +++ b/sdk/include/reactos/undocuser.h @@ -378,6 +378,9 @@ BOOL WINAPI RegisterUserApiHook(PUSERAPIHOOKINFO puah); BOOL WINAPI UnregisterUserApiHook(VOID); +/* WNET undocumented functions */ +DWORD WINAPI WNetClearConnections(DWORD dwUnknown); + #ifdef __cplusplus } /* extern "C" */ #endif /* defined(__cplusplus) */
6 years, 3 months
1
0
0
0
01/03: [MPR] Implement WNetClearConnections()
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=cf0112a6e6ce8f2a576c8…
commit cf0112a6e6ce8f2a576c840f04964aecbff04f23 Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Tue Sep 11 08:08:56 2018 +0200 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Tue Sep 11 08:30:23 2018 +0200 [MPR] Implement WNetClearConnections() This has been submitted upstream. CORE-15012 --- dll/win32/mpr/mpr.spec | 1 + dll/win32/mpr/wnet.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/dll/win32/mpr/mpr.spec b/dll/win32/mpr/mpr.spec index ec17ebdb24..b75900bafd 100644 --- a/dll/win32/mpr/mpr.spec +++ b/dll/win32/mpr/mpr.spec @@ -55,6 +55,7 @@ @ stdcall WNetCancelConnection2W(wstr long long) @ stdcall WNetCancelConnectionA(str long) @ stdcall WNetCancelConnectionW(wstr long) +@ stdcall WNetClearConnections(long) @ stdcall WNetCloseEnum(long) @ stdcall WNetConnectionDialog1A(ptr) @ stdcall WNetConnectionDialog1W(ptr) diff --git a/dll/win32/mpr/wnet.c b/dll/win32/mpr/wnet.c index 82c9302849..75d6aef987 100644 --- a/dll/win32/mpr/wnet.c +++ b/dll/win32/mpr/wnet.c @@ -2646,6 +2646,64 @@ DWORD WINAPI WNetGetUniversalNameW ( LPCWSTR lpLocalPath, DWORD dwInfoLevel, return err; } +#ifdef __REACTOS__ +/***************************************************************** + * WNetClearConnections [MPR.@] + */ +DWORD WINAPI WNetClearConnections ( DWORD unknown ) +{ + HANDLE connected; + DWORD ret, size, count; + NETRESOURCEW * resources, * iter; + + ret = WNetOpenEnumW(RESOURCE_CONNECTED, RESOURCETYPE_ANY, 0, NULL, &connected); + if (ret != WN_SUCCESS) + { + if (ret != WN_NO_NETWORK) + { + return ret; + } + + /* Means no provider, then, clearing is OK */ + return WN_SUCCESS; + } + + size = 0x1000; + resources = HeapAlloc(GetProcessHeap(), 0, size); + if (!resources) + { + WNetCloseEnum(connected); + return WN_OUT_OF_MEMORY; + } + + do + { + size = 0x1000; + count = -1; + + memset(resources, 0, size); + ret = WNetEnumResourceW(connected, &count, resources, &size); + if (ret == WN_SUCCESS || ret == WN_MORE_DATA) + { + iter = resources; + for (; count; count--) + { + WNetCancelConnection2W(iter->lpLocalName, 0, TRUE); + + iter++; + } + } + else + break; + } while (ret != WN_NO_MORE_ENTRIES); + + HeapFree(GetProcessHeap(), 0, resources); + WNetCloseEnum(connected); + + return ret; +} +#endif + /*
6 years, 3 months
1
0
0
0
01/01: [NETAPI32] Implement NetGroupGetUsers
by Eric Kohl
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=74620c94d33e51c2e0249…
commit 74620c94d33e51c2e02496ed70143a373fc82f8f Author: Eric Kohl <eric.kohl(a)reactos.org> AuthorDate: Mon Sep 10 22:04:53 2018 +0200 Commit: Eric Kohl <eric.kohl(a)reactos.org> CommitDate: Mon Sep 10 22:05:49 2018 +0200 [NETAPI32] Implement NetGroupGetUsers --- dll/win32/netapi32/group.c | 22 ---- dll/win32/netapi32/group_new.c | 267 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 267 insertions(+), 22 deletions(-) diff --git a/dll/win32/netapi32/group.c b/dll/win32/netapi32/group.c index efb46e86c1..b252111b3c 100644 --- a/dll/win32/netapi32/group.c +++ b/dll/win32/netapi32/group.c @@ -23,28 +23,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(netapi32); -/************************************************************ - * NetGroupGetUsers (NETAPI32.@) - * - */ -NET_API_STATUS -WINAPI -NetGroupGetUsers(IN LPCWSTR servername, - IN LPCWSTR groupname, - IN DWORD level, - OUT LPBYTE *bufptr, - IN DWORD prefmaxlen, - OUT LPDWORD entriesread, - OUT LPDWORD totalentries, - IN OUT PDWORD_PTR resume_handle) -{ - FIXME("(%s, %s, %d, %p, %d, %p, %p, %p) stub!\n", debugstr_w(servername), - debugstr_w(groupname), level, bufptr, prefmaxlen, entriesread, - totalentries, resume_handle); - return ERROR_ACCESS_DENIED; -} - - /************************************************************ * NetGroupSetUsers (NETAPI32.@) * diff --git a/dll/win32/netapi32/group_new.c b/dll/win32/netapi32/group_new.c index 743e685c94..dbf5a3bdf6 100644 --- a/dll/win32/netapi32/group_new.c +++ b/dll/win32/netapi32/group_new.c @@ -32,6 +32,21 @@ typedef struct _ENUM_CONTEXT ENUM_PHASE Phase; } ENUM_CONTEXT, *PENUM_CONTEXT; +typedef struct _USER_ENUM_CONTEXT +{ + SAM_HANDLE ServerHandle; + SAM_HANDLE DomainHandle; + SAM_HANDLE GroupHandle; + + ULONG MemberCount; + PULONG MemberIds; + PULONG Attributes; + PUNICODE_STRING Names; + + ULONG Start; + ULONG Count; +} USER_ENUM_CONTEXT, *PUSER_ENUM_CONTEXT; + /* FUNCTIONS *****************************************************************/ @@ -1107,6 +1122,258 @@ done: } +NET_API_STATUS +WINAPI +NetGroupGetUsers( + _In_opt_ LPCWSTR servername, + _In_ LPCWSTR groupname, + _In_ DWORD level, + _Out_ LPBYTE *bufptr, + _In_ DWORD prefmaxlen, + _Out_ LPDWORD entriesread, + _Out_ LPDWORD totalentries, + _Inout_ PDWORD_PTR resume_handle) +{ + UNICODE_STRING ServerName; + UNICODE_STRING GroupName; + PGROUP_USERS_INFO_0 UserInfo0; + PGROUP_USERS_INFO_1 UserInfo1; + PUSER_ENUM_CONTEXT EnumContext = NULL; + PVOID Buffer = NULL; + ULONG i, idx, Size; + PWSTR Ptr; + NET_API_STATUS ApiStatus = NERR_Success; + NTSTATUS Status = STATUS_SUCCESS; + + TRACE("NetGroupGetUsers(%s, %s, %d, %p, %d, %p, %p, %p)\n", + debugstr_w(servername), debugstr_w(groupname), level, bufptr, + prefmaxlen, entriesread, totalentries, resume_handle); + + *entriesread = 0; + *totalentries = 0; + *bufptr = NULL; + + if (servername != NULL) + RtlInitUnicodeString(&ServerName, servername); + + RtlInitUnicodeString(&GroupName, groupname); + + if (resume_handle != NULL && *resume_handle != 0) + { + EnumContext = (PUSER_ENUM_CONTEXT)*resume_handle; + } + else + { + ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext); + if (ApiStatus != NERR_Success) + goto done; + + EnumContext->MemberCount = 0; + EnumContext->MemberIds = NULL; + EnumContext->Attributes = NULL; + EnumContext->Names = NULL; + EnumContext->Start = 0; + EnumContext->Count = 0; + + /* Connect to the SAM Server */ + Status = SamConnect((servername != NULL) ? &ServerName : NULL, + &EnumContext->ServerHandle, + SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, + NULL); + if (!NT_SUCCESS(Status)) + { + ERR("SamConnect failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + /* Open the Acount Domain */ + Status = OpenAccountDomain(EnumContext->ServerHandle, + (servername != NULL) ? &ServerName : NULL, + DOMAIN_LOOKUP, + &EnumContext->DomainHandle); + if (!NT_SUCCESS(Status)) + { + ERR("OpenAccountDomain failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + /* Open the group account */ + ApiStatus = OpenGroupByName(EnumContext->DomainHandle, + &GroupName, + GROUP_LIST_MEMBERS, + &EnumContext->GroupHandle, + NULL); + if (ApiStatus != NERR_Success) + { + ERR("OpenGroupByName failed (ApiStatus %lu)\n", ApiStatus); + if (ApiStatus == ERROR_NONE_MAPPED) + ApiStatus = NERR_GroupNotFound; + goto done; + } + + /* Get the group members */ + Status = SamGetMembersInGroup(EnumContext->GroupHandle, + &EnumContext->MemberIds, + &EnumContext->Attributes, + &EnumContext->MemberCount); + if (!NT_SUCCESS(Status)) + { + ERR("SamGetMembersInGroup failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + if (EnumContext->MemberCount > 0) + { + /* Get all member names */ + Status = SamLookupIdsInDomain(EnumContext->DomainHandle, + EnumContext->MemberCount, + EnumContext->MemberIds, + &EnumContext->Names, + NULL); + if (!NT_SUCCESS(Status)) + { + ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + } + } + + /* Calculate the required buffer size */ + Size = 0; + if (prefmaxlen == -1) + { + Size = EnumContext->MemberCount * + ((level == 0) ? sizeof(GROUP_USERS_INFO_0) : sizeof(GROUP_USERS_INFO_1)); + for (i = EnumContext->Start; i < EnumContext->MemberCount; i++) + Size += EnumContext->Names[i].Length + sizeof(WCHAR); + + EnumContext->Count = EnumContext->MemberCount; + } + else + { + for (i = EnumContext->Start; i < EnumContext->MemberCount; i++) + { + Size += (level == 0) ? sizeof(GROUP_USERS_INFO_0) : sizeof(GROUP_USERS_INFO_1); + Size += EnumContext->Names[i].Length + sizeof(WCHAR); + + EnumContext->Count++; + + if (Size >= prefmaxlen) + break; + } + } + + TRACE("Buffer size: %lu\n", Size); + + /* Allocate and clear the buffer */ + ApiStatus = NetApiBufferAllocate(Size, &Buffer); + if (ApiStatus != NERR_Success) + goto done; + + ZeroMemory(Buffer, Size); + + /* Fill the buffer */ + if (level == 0) + Ptr = (PWCHAR)((LONG_PTR)Buffer + EnumContext->Count * sizeof(GROUP_USERS_INFO_0)); + else + Ptr = (PWCHAR)((LONG_PTR)Buffer + EnumContext->Count * sizeof(GROUP_USERS_INFO_1)); + + for (i = 0; i < EnumContext->Count; i++) + { + idx = EnumContext->Start + i; + + if (level == 0) + { + UserInfo0 = (PGROUP_USERS_INFO_0)Buffer; + + UserInfo0[i].grui0_name = Ptr; + + memcpy(UserInfo0[i].grui0_name, + EnumContext->Names[idx].Buffer, + EnumContext->Names[idx].Length); + UserInfo0[i].grui0_name[EnumContext->Names[idx].Length / sizeof(WCHAR)] = UNICODE_NULL; + + Ptr = (PWSTR)((ULONG_PTR)Ptr + EnumContext->Names[idx].Length + sizeof(WCHAR)); + } + else + { + UserInfo1 = (PGROUP_USERS_INFO_1)Buffer; + + UserInfo1[i].grui1_name = Ptr; + + memcpy(UserInfo1[i].grui1_name, + EnumContext->Names[idx].Buffer, + EnumContext->Names[idx].Length); + UserInfo1[i].grui1_name[EnumContext->Names[idx].Length / sizeof(WCHAR)] = UNICODE_NULL; + + UserInfo1[i].grui1_attributes = EnumContext->Attributes[idx]; + + Ptr = (PWSTR)((ULONG_PTR)Ptr + EnumContext->Names[idx].Length + sizeof(WCHAR)); + } + } + + /* Set the new start index */ + EnumContext->Start += EnumContext->Count; + + /* Only return ERROR_MORE_DATA if we are not done yet */ + if (EnumContext->MemberCount > EnumContext->Start) + ApiStatus = ERROR_MORE_DATA; + else + ApiStatus = NERR_Success; + +done: + if (EnumContext != NULL) + { + *entriesread = EnumContext->Count; + *totalentries = EnumContext->MemberCount; + } + + if (resume_handle == NULL || ApiStatus != ERROR_MORE_DATA) + { + if (EnumContext != NULL) + { + if (EnumContext->Names != NULL) + { + for (i = 0; i < EnumContext->MemberCount; i++) + SamFreeMemory(EnumContext->Names[i].Buffer); + + SamFreeMemory(EnumContext->Names); + } + + if (EnumContext->Attributes != NULL) + SamFreeMemory(EnumContext->Attributes); + + if (EnumContext->MemberIds != NULL) + SamFreeMemory(EnumContext->MemberIds); + + + if (EnumContext->GroupHandle != NULL) + SamCloseHandle(EnumContext->GroupHandle); + + if (EnumContext->DomainHandle != NULL) + SamCloseHandle(EnumContext->DomainHandle); + + if (EnumContext->ServerHandle != NULL) + SamCloseHandle(EnumContext->ServerHandle); + + NetApiBufferFree(EnumContext); + EnumContext = NULL; + } + } + + *bufptr = (LPBYTE)Buffer; + + if (resume_handle != NULL) + *resume_handle = (DWORD_PTR)EnumContext; + + return ApiStatus; +} + + NET_API_STATUS WINAPI NetGroupSetInfo(
6 years, 3 months
1
0
0
0
01/01: [FREETYPE] Fix Regression "Monospaced font in LibreOffice" CORE-15018
by Joachim Henze
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=31c981c02a8c1aa2d686e…
commit 31c981c02a8c1aa2d686e2efc0a1debecd16ffa8 Author: Joachim Henze <Joachim.Henze(a)reactos.org> AuthorDate: Mon Sep 10 17:51:59 2018 +0200 Commit: Joachim Henze <Joachim.Henze(a)reactos.org> CommitDate: Mon Sep 10 17:51:59 2018 +0200 [FREETYPE] Fix Regression "Monospaced font in LibreOffice" CORE-15018 LibreOffice started to show GUI in a mono-spaced font after 0.4.10-dev-466-g 35f62fc5ba0b69e7335ff41400cb3b45660f4557 We can fix this by partial revert as proposed by Katayama Hirofumi MZ, who was author of those changes as well. We revert the changes in penalty system here. --- win32ss/gdi/ntgdi/freetype.c | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/win32ss/gdi/ntgdi/freetype.c b/win32ss/gdi/ntgdi/freetype.c index e172c5c537..12c88143e9 100644 --- a/win32ss/gdi/ntgdi/freetype.c +++ b/win32ss/gdi/ntgdi/freetype.c @@ -4274,7 +4274,7 @@ GetFontPenalty(const LOGFONTW * LogFont, Byte = (LogFont->lfPitchAndFamily & 0x0F); if (Byte == DEFAULT_PITCH) Byte = VARIABLE_PITCH; - if ((Byte & FIXED_PITCH) || (Byte & MONO_FONT)) + if (Byte == FIXED_PITCH) { if (TM->tmPitchAndFamily & _TMPF_VARIABLE_PITCH) { @@ -4284,7 +4284,7 @@ GetFontPenalty(const LOGFONTW * LogFont, Penalty += 15000; } } - if (Byte & VARIABLE_PITCH) + if (Byte == VARIABLE_PITCH) { if (!(TM->tmPitchAndFamily & _TMPF_VARIABLE_PITCH)) { @@ -4335,37 +4335,12 @@ GetFontPenalty(const LOGFONTW * LogFont, Byte = (LogFont->lfPitchAndFamily & 0xF0); if (Byte != FF_DONTCARE) { - if (Byte & FF_MODERN) - { - if (TM->tmPitchAndFamily & _TMPF_VARIABLE_PITCH) - { - /* FixedPitch Penalty 15000 */ - /* Requested a fixed pitch font, but the candidate is a - variable pitch font. */ - Penalty += 15000; - } - } - - if ((Byte & FF_ROMAN) || (Byte & FF_SWISS)) - { - if (!(TM->tmPitchAndFamily & _TMPF_VARIABLE_PITCH)) - { - /* PitchVariable Penalty 350 */ - /* Requested a variable pitch font, but the candidate is not a - variable pitch font. */ - Penalty += 350; - } - } - -#define FF_MASK (FF_DECORATIVE | FF_SCRIPT | FF_SWISS) - if ((Byte & FF_MASK) != (TM->tmPitchAndFamily & FF_MASK)) + if (Byte != (TM->tmPitchAndFamily & 0xF0)) { /* Family Penalty 9000 */ /* Requested a family, but the candidate's family is different. */ Penalty += 9000; } -#undef FF_MASK - if ((TM->tmPitchAndFamily & 0xF0) == FF_DONTCARE) { /* FamilyUnknown Penalty 8000 */
6 years, 3 months
1
0
0
0
01/01: [USBEHCI_NEW] Bring-in the USB EHCI miniport driver created by Vadim Galyant. (#301)
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3bf751e0461dd0a9c50f4…
commit 3bf751e0461dd0a9c50f4100c49bb3f3de63faf0 Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Mon Sep 10 08:05:35 2018 +0100 Commit: Thomas Faber <18138474+ThFabba(a)users.noreply.github.com> CommitDate: Mon Sep 10 09:05:35 2018 +0200 [USBEHCI_NEW] Bring-in the USB EHCI miniport driver created by Vadim Galyant. (#301) --- drivers/usb/CMakeLists.txt | 1 + drivers/usb/usbehci_new/CMakeLists.txt | 16 + drivers/usb/usbehci_new/dbg_ehci.h | 51 + drivers/usb/usbehci_new/debug.c | 40 + drivers/usb/usbehci_new/guid.c | 9 + drivers/usb/usbehci_new/hardware.h | 417 +++ drivers/usb/usbehci_new/roothub.c | 710 +++++ drivers/usb/usbehci_new/usbehci.c | 3696 ++++++++++++++++++++++++ drivers/usb/usbehci_new/usbehci.h | 337 +++ drivers/usb/usbehci_new/usbehci.rc | 5 + sdk/include/reactos/drivers/usbport/usbmport.h | 2 + 11 files changed, 5284 insertions(+) diff --git a/drivers/usb/CMakeLists.txt b/drivers/usb/CMakeLists.txt index 72b486972c..ec555bbedb 100644 --- a/drivers/usb/CMakeLists.txt +++ b/drivers/usb/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(usbccgp) add_subdirectory(usbd) add_subdirectory(usbehci) +#add_subdirectory(usbehci_new) add_subdirectory(usbhub) #add_subdirectory(usbhub_new) add_subdirectory(usbohci) diff --git a/drivers/usb/usbehci_new/CMakeLists.txt b/drivers/usb/usbehci_new/CMakeLists.txt new file mode 100644 index 0000000000..f9105afc3a --- /dev/null +++ b/drivers/usb/usbehci_new/CMakeLists.txt @@ -0,0 +1,16 @@ + +list(APPEND SOURCE + debug.c + roothub.c + usbehci.c + usbehci.h) + +add_library(usbehci SHARED + ${SOURCE} + guid.c + usbehci.rc) + +set_module_type(usbehci kernelmodedriver) +add_importlibs(usbehci usbport usbd hal ntoskrnl) +add_pch(usbehci usbehci.h SOURCE) +add_cd_file(TARGET usbehci DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/usb/usbehci_new/dbg_ehci.h b/drivers/usb/usbehci_new/dbg_ehci.h new file mode 100644 index 0000000000..c2c7872c74 --- /dev/null +++ b/drivers/usb/usbehci_new/dbg_ehci.h @@ -0,0 +1,51 @@ +/* + * PROJECT: ReactOS USB EHCI Miniport Driver + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: USBEHCI debugging declarations + * COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal(a)rambler.ru> + */ + +#ifndef DBG_EHCI_H__ +#define DBG_EHCI_H__ + +#if DBG + + #ifndef NDEBUG_EHCI_TRACE + #define DPRINT_EHCI(fmt, ...) do { \ + if (DbgPrint("(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__)) \ + DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \ + } while (0) + #else + #if defined(_MSC_VER) + #define DPRINT_EHCI __noop + #else + #define DPRINT_EHCI(...) do {if(0) {DbgPrint(__VA_ARGS__);}} while(0) + #endif + #endif + + #ifndef NDEBUG_EHCI_ROOT_HUB + #define DPRINT_RH(fmt, ...) do { \ + if (DbgPrint("(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__)) \ + DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \ + } while (0) + #else + #if defined(_MSC_VER) + #define DPRINT_RH __noop + #else + #define DPRINT_RH(...) do {if(0) {DbgPrint(__VA_ARGS__);}} while(0) + #endif + #endif + +#else /* not DBG */ + + #if defined(_MSC_VER) + #define DPRINT_EHCI __noop + #define DPRINT_RH __noop + #else + #define DPRINT_EHCI(...) do {if(0) {DbgPrint(__VA_ARGS__);}} while(0) + #define DPRINT_RH(...) do {if(0) {DbgPrint(__VA_ARGS__);}} while(0) + #endif /* _MSC_VER */ + +#endif /* not DBG */ + +#endif /* DBG_EHCI_H__ */ diff --git a/drivers/usb/usbehci_new/debug.c b/drivers/usb/usbehci_new/debug.c new file mode 100644 index 0000000000..4a095ca2af --- /dev/null +++ b/drivers/usb/usbehci_new/debug.c @@ -0,0 +1,40 @@ +/* + * PROJECT: ReactOS USB EHCI Miniport Driver + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: USBEHCI debugging functions + * COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal(a)rambler.ru> + */ + +#include "usbehci.h" + +//#define NDEBUG +#include <debug.h> + +VOID +NTAPI +EHCI_DumpHwTD(IN PEHCI_HCD_TD TD) +{ + while (TD) + { + DPRINT(": TD - %p\n", TD); + DPRINT(": TD->PhysicalAddress - %lx\n", TD->PhysicalAddress); + DPRINT(": TD->HwTD.NextTD - %lx\n", TD->HwTD.NextTD); + DPRINT(": TD->HwTD.AlternateNextTD - %lx\n", TD->HwTD.AlternateNextTD); + DPRINT(": TD->HwTD.Token.AsULONG - %lx\n", TD->HwTD.Token.AsULONG); + + TD = TD->NextHcdTD; + } +} + +VOID +NTAPI +EHCI_DumpHwQH(IN PEHCI_HCD_QH QH) +{ + if (!QH) + return; + + DPRINT(": QH->sqh.HwQH.CurrentTD - %lx\n", QH->sqh.HwQH.CurrentTD); + DPRINT(": QH->sqh.HwQH.NextTD - %lx\n", QH->sqh.HwQH.NextTD); + DPRINT(": QH->sqh.HwQH.AlternateNextTD - %lx\n", QH->sqh.HwQH.AlternateNextTD); + DPRINT(": QH->sqh.HwQH.Token.AsULONG - %lx\n", QH->sqh.HwQH.Token.AsULONG); +} diff --git a/drivers/usb/usbehci_new/guid.c b/drivers/usb/usbehci_new/guid.c new file mode 100644 index 0000000000..50a60369ff --- /dev/null +++ b/drivers/usb/usbehci_new/guid.c @@ -0,0 +1,9 @@ +/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */ + +#include <wdm.h> +#include <initguid.h> +#include <wdmguid.h> +#include <hubbusif.h> +#include <usbbusif.h> + +/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */ diff --git a/drivers/usb/usbehci_new/hardware.h b/drivers/usb/usbehci_new/hardware.h new file mode 100644 index 0000000000..b0dde536e3 --- /dev/null +++ b/drivers/usb/usbehci_new/hardware.h @@ -0,0 +1,417 @@ +/* + * PROJECT: ReactOS USB EHCI Miniport Driver + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: USBEHCI hardware declarations + * COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal(a)rambler.ru> + */ + +#define EHCI_FRAME_LIST_MAX_ENTRIES 1024 // Number of frames in Frame List + +/* EHCI hardware registers */ +#define EHCI_USBCMD 0 +#define EHCI_USBSTS 1 +#define EHCI_USBINTR 2 +#define EHCI_FRINDEX 3 +#define EHCI_CTRLDSSEGMENT 4 +#define EHCI_PERIODICLISTBASE 5 +#define EHCI_ASYNCLISTBASE 6 +#define EHCI_CONFIGFLAG 16 +#define EHCI_PORTSC 17 + +#define EHCI_FLADJ_PCI_CONFIG_OFFSET 0x61 + +typedef union _EHCI_LEGACY_EXTENDED_CAPABILITY { + struct { + ULONG CapabilityID : 8; + ULONG NextCapabilityPointer : 8; + ULONG BiosOwnedSemaphore : 1; + ULONG Reserved1 : 7; + ULONG OsOwnedSemaphore : 1; + ULONG Reserved2 : 7; + }; + ULONG AsULONG; +} EHCI_LEGACY_EXTENDED_CAPABILITY; + +C_ASSERT(sizeof(EHCI_LEGACY_EXTENDED_CAPABILITY) == sizeof(ULONG)); + +typedef union _EHCI_HC_STRUCTURAL_PARAMS { + struct { + ULONG PortCount : 4; + ULONG PortPowerControl : 1; + ULONG Reserved1 : 2; + ULONG PortRouteRules : 1; + ULONG PortsPerCompanion : 4; + ULONG CompanionControllers : 4; + ULONG PortIndicators : 1; + ULONG Reserved2 : 3; + ULONG DebugPortNumber : 4; //Optional + ULONG Reserved3 : 8; + }; + ULONG AsULONG; +} EHCI_HC_STRUCTURAL_PARAMS; + +C_ASSERT(sizeof(EHCI_HC_STRUCTURAL_PARAMS) == sizeof(ULONG)); + +typedef union _EHCI_HC_CAPABILITY_PARAMS { + struct { + ULONG Addressing64bitCapability : 1; + ULONG IsProgrammableFrameList : 1; + ULONG IsScheduleParkSupport : 1; + ULONG Reserved1 : 1; + ULONG IsoSchedulingThreshold : 4; + ULONG ExtCapabilitiesPointer : 8; // (EECP) + ULONG Reserved2 : 16; + }; + ULONG AsULONG; +} EHCI_HC_CAPABILITY_PARAMS; + +C_ASSERT(sizeof(EHCI_HC_CAPABILITY_PARAMS) == sizeof(ULONG)); + +typedef struct _EHCI_HC_CAPABILITY_REGISTERS { + UCHAR RegistersLength; // RO + UCHAR Reserved; // RO + USHORT InterfaceVersion; // RO + EHCI_HC_STRUCTURAL_PARAMS StructParameters; // RO + EHCI_HC_CAPABILITY_PARAMS CapParameters; // RO + UCHAR CompanionPortRouteDesc[8]; // RO +} EHCI_HC_CAPABILITY_REGISTERS, *PEHCI_HC_CAPABILITY_REGISTERS; + +typedef union _EHCI_USB_COMMAND { + struct { + ULONG Run : 1; + ULONG Reset : 1; + ULONG FrameListSize : 2; + ULONG PeriodicEnable : 1; + ULONG AsynchronousEnable : 1; + ULONG InterruptAdvanceDoorbell : 1; + ULONG LightResetHC : 1; // optional + ULONG AsynchronousParkModeCount : 2; // optional + ULONG Reserved1 : 1; + ULONG AsynchronousParkModeEnable : 1; // optional + ULONG Reserved2 : 4; + ULONG InterruptThreshold : 8; + ULONG Reserved3 : 8; + }; + ULONG AsULONG; +} EHCI_USB_COMMAND; + +C_ASSERT(sizeof(EHCI_USB_COMMAND) == sizeof(ULONG)); + +typedef union _EHCI_USB_STATUS { + struct { + ULONG Interrupt : 1; + ULONG ErrorInterrupt : 1; + ULONG PortChangeDetect : 1; + ULONG FrameListRollover : 1; + ULONG HostSystemError : 1; + ULONG InterruptOnAsyncAdvance : 1; + ULONG Reserved1 : 6; + ULONG HCHalted : 1; + ULONG Reclamation : 1; + ULONG PeriodicStatus : 1; + ULONG AsynchronousStatus : 1; + ULONG Reserved2 : 16; + }; + ULONG AsULONG; +} EHCI_USB_STATUS; + +C_ASSERT(sizeof(EHCI_USB_STATUS) == sizeof(ULONG)); + +#define EHCI_INTERRUPT_MASK 0x3F + +typedef union _EHCI_INTERRUPT_ENABLE { + struct { + ULONG Interrupt : 1; + ULONG ErrorInterrupt : 1; + ULONG PortChangeInterrupt : 1; + ULONG FrameListRollover : 1; + ULONG HostSystemError : 1; + ULONG InterruptOnAsyncAdvance : 1; + ULONG Reserved : 26; + }; + ULONG AsULONG; +} EHCI_INTERRUPT_ENABLE; + +C_ASSERT(sizeof(EHCI_INTERRUPT_ENABLE) == sizeof(ULONG)); + +#define EHCI_LINE_STATUS_K_STATE_LOW_SPEED 1 +#define EHCI_PORT_OWNER_COMPANION_CONTROLLER 1 + +typedef union _EHCI_PORT_STATUS_CONTROL { + struct { + ULONG CurrentConnectStatus : 1; + ULONG ConnectStatusChange : 1; + ULONG PortEnabledDisabled : 1; + ULONG PortEnableDisableChange : 1; + ULONG OverCurrentActive : 1; + ULONG OverCurrentChange : 1; + ULONG ForcePortResume : 1; + ULONG Suspend : 1; + ULONG PortReset : 1; + ULONG Reserved1 : 1; + ULONG LineStatus : 2; + ULONG PortPower : 1; + ULONG PortOwner : 1; + ULONG PortIndicatorControl : 2; + ULONG PortTestControl : 4; + ULONG WakeOnConnectEnable : 1; + ULONG WakeOnDisconnectEnable : 1; + ULONG WakeOnOverCurrentEnable : 1; + ULONG Reserved2 : 9; + }; + ULONG AsULONG; +} EHCI_PORT_STATUS_CONTROL; + +C_ASSERT(sizeof(EHCI_PORT_STATUS_CONTROL) == sizeof(ULONG)); + +/* FRINDEX Frame Index Register */ +#define EHCI_FRINDEX_FRAME_MASK 0x7FF +#define EHCI_FRINDEX_INDEX_MASK 0x3FF + +#define EHCI_CONFIG_FLAG_CONFIGURED 1 + +typedef struct _EHCI_HW_REGISTERS { + EHCI_USB_COMMAND HcCommand; // RO, R/W (field dependent), WO + EHCI_USB_STATUS HcStatus; // RO, R/W, R/WC, (field dependent) + EHCI_INTERRUPT_ENABLE HcInterruptEnable; // R/W + ULONG FrameIndex; // R/W (Writes must be DWord Writes) + ULONG SegmentSelector; // R/W (Writes must be DWord Writes) + ULONG PeriodicListBase; // R/W (Writes must be DWord Writes) + ULONG AsyncListBase; // Read/Write (Writes must be DWord Writes) + ULONG Reserved[9]; + ULONG ConfigFlag; // R/W + EHCI_PORT_STATUS_CONTROL PortControl[15]; // (1-15) RO, R/W, R/WC (field dependent) +} EHCI_HW_REGISTERS, *PEHCI_HW_REGISTERS; + +/* Link Pointer */ +#define EHCI_LINK_TYPE_iTD 0 // isochronous transfer descriptor +#define EHCI_LINK_TYPE_QH 1 // queue head +#define EHCI_LINK_TYPE_siTD 2 // split transaction isochronous transfer +#define EHCI_LINK_TYPE_FSTN 3 // frame span traversal node + +/* Used for QHs and qTDs to mark Pointers as the end */ +#define TERMINATE_POINTER 1 + +#define LINK_POINTER_MASK 0xFFFFFFE0 + +typedef union _EHCI_LINK_POINTER { + struct { + ULONG Terminate : 1; + ULONG Type : 2; + ULONG Reserved : 2; + ULONG Address : 27; + }; + ULONG AsULONG; +} EHCI_LINK_POINTER; + +C_ASSERT(sizeof(EHCI_LINK_POINTER) == sizeof(ULONG)); + +/* Isochronous (High-Speed) Transfer Descriptor (iTD) */ +typedef union _EHCI_TRANSACTION_CONTROL { + struct { + ULONG xOffset : 12; + ULONG PageSelect : 3; + ULONG InterruptOnComplete : 1; + ULONG xLength : 12; + ULONG Status : 4; + }; + ULONG AsULONG; +} EHCI_TRANSACTION_CONTROL; + +C_ASSERT(sizeof(EHCI_TRANSACTION_CONTROL) == sizeof(ULONG)); + +typedef union _EHCI_TRANSACTION_BUFFER { + struct { + ULONG DeviceAddress : 7; + ULONG Reserved1 : 1; + ULONG EndpointNumber : 4; + ULONG DataBuffer0 : 20; + }; + struct { + ULONG MaximumPacketSize : 11; + ULONG Direction : 1; + ULONG DataBuffer1 : 20; + }; + struct { + ULONG Multi : 2; + ULONG Reserved2 : 10; + ULONG DataBuffer2 : 20; + }; + struct { + ULONG Reserved3 : 12; + ULONG DataBuffer : 20; + }; + ULONG AsULONG; +} EHCI_TRANSACTION_BUFFER; + +C_ASSERT(sizeof(EHCI_TRANSACTION_BUFFER) == sizeof(ULONG)); + +typedef struct _EHCI_ISOCHRONOUS_TD { // must be aligned on a 32-byte boundary + EHCI_LINK_POINTER NextLink; + EHCI_TRANSACTION_CONTROL Transaction[8]; + EHCI_TRANSACTION_BUFFER Buffer[7]; + ULONG ExtendedBuffer[7]; +} EHCI_ISOCHRONOUS_TD, *PEHCI_ISOCHRONOUS_TD; + +C_ASSERT(sizeof(EHCI_ISOCHRONOUS_TD) == 92); + +/* Split Transaction Isochronous Transfer Descriptor (siTD) */ +typedef union _EHCI_FS_ENDPOINT_PARAMS { + struct { + ULONG DeviceAddress : 7; + ULONG Reserved1 : 1; + ULONG EndpointNumber : 4; + ULONG Reserved2 : 4; + ULONG HubAddress : 7; + ULONG Reserved3 : 1; + ULONG PortNumber : 7; + ULONG Direction : 1; + }; + ULONG AsULONG; +} EHCI_FS_ENDPOINT_PARAMS; + +C_ASSERT(sizeof(EHCI_FS_ENDPOINT_PARAMS) == sizeof(ULONG)); + +typedef union _EHCI_MICROFRAME_CONTROL { + struct { + ULONG StartMask : 8; + ULONG CompletionMask : 8; + ULONG Reserved : 16; + }; + ULONG AsULONG; +} EHCI_MICROFRAME_CONTROL; + +C_ASSERT(sizeof(EHCI_MICROFRAME_CONTROL) == sizeof(ULONG)); + +typedef union _EHCI_SPLIT_TRANSFER_STATE { + struct { + ULONG Status : 8; + ULONG ProgressMask : 8; + ULONG TotalBytes : 10; + ULONG Reserved : 4; + ULONG PageSelect : 1; + ULONG InterruptOnComplete : 1; + }; + ULONG AsULONG; +} EHCI_SPLIT_TRANSFER_STATE; + +C_ASSERT(sizeof(EHCI_SPLIT_TRANSFER_STATE) == sizeof(ULONG)); + +typedef union _EHCI_SPLIT_BUFFER_POINTER { + struct { + ULONG CurrentOffset : 12; + ULONG DataBuffer0 : 20; + }; + struct { + ULONG TransactionCount : 3; + ULONG TransactionPosition : 2; + ULONG Reserved : 7; + ULONG DataBuffer1 : 20; + }; + ULONG AsULONG; +} EHCI_SPLIT_BUFFER_POINTER; + +C_ASSERT(sizeof(EHCI_SPLIT_BUFFER_POINTER) == sizeof(ULONG)); + +typedef struct _EHCI_SPLIT_ISOCHRONOUS_TD { // must be aligned on a 32-byte boundary + EHCI_LINK_POINTER NextLink; + EHCI_FS_ENDPOINT_PARAMS EndpointCharacteristics; + EHCI_MICROFRAME_CONTROL MicroFrameControl; + EHCI_SPLIT_TRANSFER_STATE TransferState; + EHCI_SPLIT_BUFFER_POINTER Buffer[2]; + ULONG BackPointer; + ULONG ExtendedBuffer[2]; +} EHCI_SPLIT_ISOCHRONOUS_TD, *PEHCI_SPLIT_ISOCHRONOUS_TD; + +C_ASSERT(sizeof(EHCI_SPLIT_ISOCHRONOUS_TD) == 36); + +/* Queue Element Transfer Descriptor (qTD) */ +#define EHCI_MAX_QTD_BUFFER_PAGES 5 + +#define EHCI_TOKEN_STATUS_ACTIVE (1 << 7) +#define EHCI_TOKEN_STATUS_HALTED (1 << 6) +#define EHCI_TOKEN_STATUS_DATA_BUFFER_ERROR (1 << 5) +#define EHCI_TOKEN_STATUS_BABBLE_DETECTED (1 << 4) +#define EHCI_TOKEN_STATUS_TRANSACTION_ERROR (1 << 3) +#define EHCI_TOKEN_STATUS_MISSED_MICROFRAME (1 << 2) +#define EHCI_TOKEN_STATUS_SPLIT_STATE (1 << 1) +#define EHCI_TOKEN_STATUS_PING_STATE (1 << 0) + +#define EHCI_TD_TOKEN_PID_OUT 0 +#define EHCI_TD_TOKEN_PID_IN 1 +#define EHCI_TD_TOKEN_PID_SETUP 2 +#define EHCI_TD_TOKEN_PID_RESERVED 3 + +typedef union _EHCI_TD_TOKEN { + struct { + ULONG Status : 8; + ULONG PIDCode : 2; + ULONG ErrorCounter : 2; + ULONG CurrentPage : 3; + ULONG InterruptOnComplete : 1; + ULONG TransferBytes : 15; + ULONG DataToggle : 1; + }; + ULONG AsULONG; +} EHCI_TD_TOKEN, *PEHCI_TD_TOKEN; + +C_ASSERT(sizeof(EHCI_TD_TOKEN) == sizeof(ULONG)); + +typedef struct _EHCI_QUEUE_TD { // must be aligned on 32-byte boundaries + ULONG NextTD; + ULONG AlternateNextTD; + EHCI_TD_TOKEN Token; + ULONG Buffer[5]; + ULONG ExtendedBuffer[5]; +} EHCI_QUEUE_TD, *PEHCI_QUEUE_TD; + +C_ASSERT(sizeof(EHCI_QUEUE_TD) == 52); + +/* Queue Head */ +#define EHCI_QH_EP_FULL_SPEED 0 +#define EHCI_QH_EP_LOW_SPEED 1 +#define EHCI_QH_EP_HIGH_SPEED 2 + +typedef union _EHCI_QH_EP_PARAMS { + struct { + ULONG DeviceAddress : 7; + ULONG InactivateOnNextTransaction : 1; + ULONG EndpointNumber : 4; + ULONG EndpointSpeed : 2; + ULONG DataToggleControl : 1; + ULONG HeadReclamationListFlag : 1; + ULONG MaximumPacketLength : 11; // corresponds to the maximum packet size of the associated endpoint (wMaxPacketSize). + ULONG ControlEndpointFlag : 1; + ULONG NakCountReload : 4; + }; + ULONG AsULONG; +} EHCI_QH_EP_PARAMS; + +C_ASSERT(sizeof(EHCI_QH_EP_PARAMS) == sizeof(ULONG)); + +typedef union _EHCI_QH_EP_CAPS { + struct { + ULONG InterruptMask : 8; + ULONG SplitCompletionMask : 8; + ULONG HubAddr : 7; + ULONG PortNumber : 7; + ULONG PipeMultiplier : 2; + }; + ULONG AsULONG; +} EHCI_QH_EP_CAPS; + +C_ASSERT(sizeof(EHCI_QH_EP_CAPS) == sizeof(ULONG)); + +typedef struct _EHCI_QUEUE_HEAD { // must be aligned on 32-byte boundaries + EHCI_LINK_POINTER HorizontalLink; + EHCI_QH_EP_PARAMS EndpointParams; + EHCI_QH_EP_CAPS EndpointCaps; + ULONG CurrentTD; + ULONG NextTD; + ULONG AlternateNextTD; + EHCI_TD_TOKEN Token; + ULONG Buffer[5]; + ULONG ExtendedBuffer[5]; +} EHCI_QUEUE_HEAD, *PEHCI_QUEUE_HEAD; + +C_ASSERT(sizeof(EHCI_QUEUE_HEAD) == 68); diff --git a/drivers/usb/usbehci_new/roothub.c b/drivers/usb/usbehci_new/roothub.c new file mode 100644 index 0000000000..67b39bfba9 --- /dev/null +++ b/drivers/usb/usbehci_new/roothub.c @@ -0,0 +1,710 @@ +/* + * PROJECT: ReactOS USB EHCI Miniport Driver + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: USBEHCI root hub functions + * COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal(a)rambler.ru> + */ + +#include "usbehci.h" + +#define NDEBUG +#include <debug.h> + +#define NDEBUG_EHCI_ROOT_HUB +#include "dbg_ehci.h" + +MPSTATUS +NTAPI +EHCI_RH_ChirpRootPort(IN PVOID ehciExtension, + IN USHORT Port) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG PortStatusReg; + EHCI_PORT_STATUS_CONTROL PortSC; + ULONG PortBit; + ULONG ix; + + DPRINT_RH("EHCI_RH_ChirpRootPort: Port - %x\n", Port); + ASSERT(Port != 0); + + PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG; + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + DPRINT_RH("EHCI_RH_ChirpRootPort: PortSC - %X\n", PortSC.AsULONG); + + PortBit = 1 << (Port - 1); + + if (PortBit & EhciExtension->ResetPortBits) + { + DPRINT_RH("EHCI_RH_ChirpRootPort: Skip port - %x\n", Port); + return MP_STATUS_SUCCESS; + } + + if (PortSC.PortPower == 0) + { + DPRINT_RH("EHCI_RH_ChirpRootPort: Skip port - %x\n", Port); + return MP_STATUS_SUCCESS; + } + + if (PortSC.CurrentConnectStatus == 0 || + PortSC.PortEnabledDisabled == 1 || + PortSC.PortOwner == EHCI_PORT_OWNER_COMPANION_CONTROLLER) + { + DPRINT_RH("EHCI_RH_ChirpRootPort: No port - %x\n", Port); + return MP_STATUS_SUCCESS; + } + + if (PortSC.LineStatus == EHCI_LINE_STATUS_K_STATE_LOW_SPEED && + PortSC.Suspend == 0 && + PortSC.CurrentConnectStatus == 1) + { + /* Attached device is not a high-speed device. + Release ownership of the port to a selected HC. + Companion HC owns and controls the port. Section 4.2 */ + PortSC.PortOwner = EHCI_PORT_OWNER_COMPANION_CONTROLLER; + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + + DPRINT_RH("EHCI_RH_ChirpRootPort: Companion HC port - %x\n", Port); + return MP_STATUS_SUCCESS; + } + + DPRINT("EHCI_RH_ChirpRootPort: EhciExtension - %p, Port - %x\n", + EhciExtension, + Port); + + PortSC.PortEnabledDisabled = 0; + PortSC.PortReset = 1; + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + + RegPacket.UsbPortWait(EhciExtension, 10); + + do + { + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + PortSC.ConnectStatusChange = 0; + PortSC.PortEnableDisableChange = 0; + PortSC.OverCurrentChange = 0; + PortSC.PortReset = 0; + + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + + for (ix = 0; ix <= 500; ix += 20) + { + KeStallExecutionProcessor(20); + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + DPRINT_RH("EHCI_RH_ChirpRootPort: Reset port - %x\n", Port); + + if (PortSC.PortReset == 0) + break; + } + } + while (PortSC.PortReset == 1); + + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + if (PortSC.PortEnabledDisabled == 1) + { + PortSC.ConnectStatusChange = 0; + PortSC.PortEnabledDisabled = 0; + PortSC.PortEnableDisableChange = 0; + PortSC.OverCurrentChange = 0; + + RegPacket.UsbPortWait(EhciExtension, 10); + + EhciExtension->ResetPortBits |= PortBit; + + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + DPRINT_RH("EHCI_RH_ChirpRootPort: Disable port - %x\n", Port); + } + else + { + PortSC.PortOwner = EHCI_PORT_OWNER_COMPANION_CONTROLLER; + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + DPRINT_RH("EHCI_RH_ChirpRootPort: Companion HC port - %x\n", Port); + } + + return MP_STATUS_SUCCESS; +} + +VOID +NTAPI +EHCI_RH_GetRootHubData(IN PVOID ehciExtension, + IN PVOID rootHubData) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PUSBPORT_ROOT_HUB_DATA RootHubData; + USBPORT_HUB_20_CHARACTERISTICS HubCharacteristics; + + DPRINT_RH("EHCI_RH_GetRootHubData: EhciExtension - %p, rootHubData - %p\n", + EhciExtension, + rootHubData); + + RootHubData = rootHubData; + + RootHubData->NumberOfPorts = EhciExtension->NumberOfPorts; + + HubCharacteristics.AsUSHORT = 0; + + /* Logical Power Switching Mode */ + if (EhciExtension->PortPowerControl == 1) + { + /* Individual port power switching */ + HubCharacteristics.PowerControlMode = 1; + } + else + { + /* Ganged power switching (all ports� power at once) */ + HubCharacteristics.PowerControlMode = 0; + } + + HubCharacteristics.NoPowerSwitching = 0; + + /* EHCI RH is not part of a compound device */ + HubCharacteristics.PartOfCompoundDevice = 0; + + /* Global Over-current Protection */ + HubCharacteristics.OverCurrentProtectionMode = 0; + + RootHubData->HubCharacteristics.Usb20HubCharacteristics = HubCharacteristics; + + RootHubData->PowerOnToPowerGood = 2; // Time (in 2 ms intervals) + RootHubData->HubControlCurrent = 0; +} + +MPSTATUS +NTAPI +EHCI_RH_GetStatus(IN PVOID ehciExtension, + IN PUSHORT Status) +{ + DPRINT_RH("EHCI_RH_GetStatus: ... \n"); + *Status = USB_GETSTATUS_SELF_POWERED; + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_RH_GetPortStatus(IN PVOID ehciExtension, + IN USHORT Port, + IN PUSB_PORT_STATUS_AND_CHANGE PortStatus) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG PortStatusReg; + EHCI_PORT_STATUS_CONTROL PortSC; + USB_PORT_STATUS_AND_CHANGE status; + ULONG PortMaskBits; + + ASSERT(Port != 0); + + PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG; + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + if (PortSC.CurrentConnectStatus) + { + DPRINT_RH("EHCI_RH_GetPortStatus: Port - %x, PortSC.AsULONG - %X\n", + Port, + PortSC.AsULONG); + } + + PortStatus->AsUlong32 = 0; + + if (PortSC.LineStatus == EHCI_LINE_STATUS_K_STATE_LOW_SPEED && + PortSC.PortOwner != EHCI_PORT_OWNER_COMPANION_CONTROLLER && + (PortSC.PortEnabledDisabled | PortSC.Suspend) && // Enable or Suspend + PortSC.CurrentConnectStatus == 1) // Device is present + { + DPRINT("EHCI_RH_GetPortStatus: LowSpeed device detected\n"); + PortSC.PortOwner = EHCI_PORT_OWNER_COMPANION_CONTROLLER; // release ownership + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + return MP_STATUS_SUCCESS; + } + + status.AsUlong32 = 0; + + status.PortStatus.Usb20PortStatus.CurrentConnectStatus = PortSC.CurrentConnectStatus; + status.PortStatus.Usb20PortStatus.PortEnabledDisabled = PortSC.PortEnabledDisabled; + status.PortStatus.Usb20PortStatus.Suspend = PortSC.Suspend; + status.PortStatus.Usb20PortStatus.OverCurrent = PortSC.OverCurrentActive; + status.PortStatus.Usb20PortStatus.Reset = PortSC.PortReset; + status.PortStatus.Usb20PortStatus.PortPower = PortSC.PortPower; + if (PortSC.PortOwner == EHCI_PORT_OWNER_COMPANION_CONTROLLER) + status.PortStatus.Usb20PortStatus.Reserved1 = USB20_PORT_STATUS_RESERVED1_OWNED_BY_COMPANION; + + status.PortChange.Usb20PortChange.PortEnableDisableChange = PortSC.PortEnableDisableChange; + status.PortChange.Usb20PortChange.OverCurrentIndicatorChange = PortSC.OverCurrentChange; + + PortMaskBits = 1 << (Port - 1); + + if (status.PortStatus.Usb20PortStatus.CurrentConnectStatus) + status.PortStatus.Usb20PortStatus.LowSpeedDeviceAttached = 0; + + status.PortStatus.Usb20PortStatus.HighSpeedDeviceAttached = 1; + + if (PortSC.ConnectStatusChange) + EhciExtension->ConnectPortBits |= PortMaskBits; + + if (EhciExtension->FinishResetPortBits & PortMaskBits) + status.PortChange.Usb20PortChange.ResetChange = 1; + + if (EhciExtension->ConnectPortBits & PortMaskBits) + status.PortChange.Usb20PortChange.ConnectStatusChange = 1; + + if (EhciExtension->SuspendPortBits & PortMaskBits) + status.PortChange.Usb20PortChange.SuspendChange = 1; + + *PortStatus = status; + + if (status.PortStatus.Usb20PortStatus.CurrentConnectStatus) + { + DPRINT_RH("EHCI_RH_GetPortStatus: Port - %x, status.AsULONG - %X\n", + Port, + status.AsUlong32); + } + + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_RH_GetHubStatus(IN PVOID ehciExtension, + IN PUSB_HUB_STATUS_AND_CHANGE HubStatus) +{ + DPRINT_RH("EHCI_RH_GetHubStatus: ... \n"); + HubStatus->AsUlong32 = 0; + return MP_STATUS_SUCCESS; +} + +VOID +NTAPI +EHCI_RH_FinishReset(IN PVOID ehciExtension, + IN PVOID Context) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG PortStatusReg; + EHCI_PORT_STATUS_CONTROL PortSC; + PUSHORT Port = Context; + + DPRINT("EHCI_RH_FinishReset: *Port - %x\n", *Port); + + PortStatusReg = &EhciExtension->OperationalRegs->PortControl[*Port - 1].AsULONG; + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + if (PortSC.AsULONG != -1) + { + if (!PortSC.CurrentConnectStatus) + DPRINT("EHCI_RH_FinishReset: PortSC.AsULONG - %X\n", PortSC.AsULONG); + + if (PortSC.PortEnabledDisabled || + !PortSC.CurrentConnectStatus || + PortSC.ConnectStatusChange) + { + EhciExtension->FinishResetPortBits |= (1 << (*Port - 1)); + RegPacket.UsbPortInvalidateRootHub(EhciExtension); + } + else + { + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + PortSC.PortOwner = EHCI_PORT_OWNER_COMPANION_CONTROLLER; + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + EhciExtension->FinishResetPortBits |= (1 << (*Port - 1)); + } + + EhciExtension->ResetPortBits &= ~(1 << (*Port - 1)); + } +} + +VOID +NTAPI +EHCI_RH_PortResetComplete(IN PVOID ehciExtension, + IN PVOID Context) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG PortStatusReg; + EHCI_PORT_STATUS_CONTROL PortSC; + ULONG ix; + PUSHORT Port = Context; + + DPRINT("EHCI_RH_PortResetComplete: *Port - %x\n", *Port); + + PortStatusReg = &EhciExtension->OperationalRegs->PortControl[*Port - 1].AsULONG; + + do + { + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + PortSC.ConnectStatusChange = 0; + PortSC.PortEnableDisableChange = 0; + PortSC.OverCurrentChange = 0; + PortSC.PortReset = 0; + + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + + for (ix = 0; ix <= 500; ix += 20) + { + KeStallExecutionProcessor(20); + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + DPRINT("EHCI_RH_PortResetComplete: Reset port - %x\n", Port); + + if (PortSC.PortReset == 0) + break; + } + } + while (PortSC.PortReset == 1 && (PortSC.AsULONG != -1)); + + RegPacket.UsbPortRequestAsyncCallback(EhciExtension, + 50, // TimerValue + Port, + sizeof(Port), + EHCI_RH_FinishReset); +} + +MPSTATUS +NTAPI +EHCI_RH_SetFeaturePortReset(IN PVOID ehciExtension, + IN USHORT Port) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG PortStatusReg; + EHCI_PORT_STATUS_CONTROL PortSC; + + DPRINT("EHCI_RH_SetFeaturePortReset: Port - %x\n", Port); + ASSERT(Port != 0); + + PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG; + + EhciExtension->ResetPortBits |= 1 << (Port - 1); + + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + PortSC.ConnectStatusChange = 0; + PortSC.PortEnabledDisabled = 0; + PortSC.PortEnableDisableChange = 0; + PortSC.OverCurrentChange = 0; + PortSC.PortReset = 1; + + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + + RegPacket.UsbPortRequestAsyncCallback(EhciExtension, + 50, // TimerValue + &Port, + sizeof(Port), + EHCI_RH_PortResetComplete); + + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_RH_SetFeaturePortPower(IN PVOID ehciExtension, + IN USHORT Port) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG PortStatusReg; + EHCI_PORT_STATUS_CONTROL PortSC; + + DPRINT_RH("EHCI_RH_SetFeaturePortPower: Port - %x\n", Port); + ASSERT(Port != 0); + + PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG; + + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + PortSC.ConnectStatusChange = 0; + PortSC.PortEnableDisableChange = 0; + PortSC.OverCurrentChange = 0; + PortSC.PortPower = 1; + + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_RH_SetFeaturePortEnable(IN PVOID ehciExtension, + IN USHORT Port) +{ + DPRINT_RH("EHCI_RH_SetFeaturePortEnable: Not supported\n"); + ASSERT(Port != 0); + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_RH_SetFeaturePortSuspend(IN PVOID ehciExtension, + IN USHORT Port) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG PortStatusReg; + EHCI_PORT_STATUS_CONTROL PortSC; + + DPRINT("EHCI_RH_SetFeaturePortSuspend: Port - %x\n", Port); + ASSERT(Port != 0); + + PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG; + + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + PortSC.ConnectStatusChange = 0; + PortSC.PortEnableDisableChange = 0; + PortSC.OverCurrentChange = 0; + PortSC.Suspend = 1; + + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + KeStallExecutionProcessor(125); + + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_RH_ClearFeaturePortEnable(IN PVOID ehciExtension, + IN USHORT Port) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG PortStatusReg; + EHCI_PORT_STATUS_CONTROL PortSC; + + DPRINT("EHCI_RH_ClearFeaturePortEnable: Port - %x\n", Port); + ASSERT(Port != 0); + + PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG; + + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + PortSC.ConnectStatusChange = 0; + PortSC.PortEnabledDisabled = 0; + PortSC.PortEnableDisableChange = 0; + PortSC.OverCurrentChange = 0; + + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_RH_ClearFeaturePortPower(IN PVOID ehciExtension, + IN USHORT Port) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG PortStatusReg; + EHCI_PORT_STATUS_CONTROL PortSC; + + DPRINT("EHCI_RH_ClearFeaturePortPower: Port - %x\n", Port); + ASSERT(Port != 0); + + PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG; + + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + PortSC.PortPower = 0; + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + + return MP_STATUS_SUCCESS; +} + +VOID +NTAPI +EHCI_RH_PortResumeComplete(IN PVOID ehciExtension, + IN PVOID Context) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG PortStatusReg; + EHCI_PORT_STATUS_CONTROL PortSC; + PUSHORT Port = Context; + + DPRINT("EHCI_RH_PortResumeComplete: *Port - %x\n", *Port); + ASSERT(Port != 0); + + PortStatusReg = &EhciExtension->OperationalRegs->PortControl[*Port - 1].AsULONG; + + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + PortSC.ConnectStatusChange = 0; + PortSC.PortEnableDisableChange = 0; + PortSC.OverCurrentChange = 0; + PortSC.ForcePortResume = 0; + PortSC.Suspend = 0; + + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + READ_REGISTER_ULONG(PortStatusReg); + + EhciExtension->SuspendPortBits |= 1 << (*Port - 1); +} + +MPSTATUS +NTAPI +EHCI_RH_ClearFeaturePortSuspend(IN PVOID ehciExtension, + IN USHORT Port) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG PortStatusReg; + EHCI_PORT_STATUS_CONTROL PortSC; + + DPRINT("EHCI_RH_ClearFeaturePortSuspend: Port - %x\n", Port); + ASSERT(Port != 0); + + PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG; + EhciExtension->ResetPortBits |= 1 << (Port - 1); + + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + PortSC.ForcePortResume = 1; + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + + RegPacket.UsbPortRequestAsyncCallback(EhciExtension, + 50, // TimerValue + &Port, + sizeof(Port), + EHCI_RH_PortResumeComplete); + + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_RH_ClearFeaturePortEnableChange(IN PVOID ehciExtension, + IN USHORT Port) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG PortStatusReg; + EHCI_PORT_STATUS_CONTROL PortSC; + + DPRINT("EHCI_RH_ClearFeaturePortEnableChange: Port - %p\n", Port); + ASSERT(Port != 0); + + PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG; + + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + PortSC.ConnectStatusChange = 0; + PortSC.OverCurrentChange = 0; + PortSC.PortEnableDisableChange = 1; + + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_RH_ClearFeaturePortConnectChange(IN PVOID ehciExtension, + IN USHORT Port) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG PortStatusReg; + EHCI_PORT_STATUS_CONTROL PortSC; + + DPRINT_RH("EHCI_RH_ClearFeaturePortConnectChange: Port - %x\n", Port); + ASSERT(Port != 0); + + PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG; + + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + if (PortSC.ConnectStatusChange) + { + PortSC.ConnectStatusChange = 1; + PortSC.PortEnableDisableChange = 0; + PortSC.OverCurrentChange = 0; + + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + } + + EhciExtension->ConnectPortBits &= ~(1 << (Port - 1)); + + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_RH_ClearFeaturePortResetChange(IN PVOID ehciExtension, + IN USHORT Port) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + + DPRINT("EHCI_RH_ClearFeaturePortConnectChange: Port - %x\n", Port); + ASSERT(Port != 0); + + EhciExtension->FinishResetPortBits &= ~(1 << (Port - 1)); + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_RH_ClearFeaturePortSuspendChange(IN PVOID ehciExtension, + IN USHORT Port) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + + DPRINT("EHCI_RH_ClearFeaturePortSuspendChange: Port - %x\n", Port); + ASSERT(Port != 0); + + EhciExtension->SuspendPortBits &= ~(1 << (Port - 1)); + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_RH_ClearFeaturePortOvercurrentChange(IN PVOID ehciExtension, + IN USHORT Port) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG PortStatusReg; + EHCI_PORT_STATUS_CONTROL PortSC; + + DPRINT_RH("EHCI_RH_ClearFeaturePortOvercurrentChange: Port - %x\n", Port); + ASSERT(Port != 0); + + PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG; + + PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg); + + PortSC.ConnectStatusChange = 0; + PortSC.PortEnableDisableChange = 0; + PortSC.OverCurrentChange = 1; + + WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG); + + return MP_STATUS_SUCCESS; +} + +VOID +NTAPI +EHCI_RH_DisableIrq(IN PVOID ehciExtension) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG IntrStsReg; + EHCI_INTERRUPT_ENABLE IntrSts; + + DPRINT_RH("EHCI_RH_DisableIrq: ... \n"); + + IntrStsReg = &EhciExtension->OperationalRegs->HcInterruptEnable.AsULONG; + IntrSts.AsULONG = READ_REGISTER_ULONG(IntrStsReg); + + EhciExtension->InterruptMask.PortChangeInterrupt = 0; + IntrSts.PortChangeInterrupt = 0; + + if (IntrSts.Interrupt) + WRITE_REGISTER_ULONG(IntrStsReg, IntrSts.AsULONG); +} + +VOID +NTAPI +EHCI_RH_EnableIrq(IN PVOID ehciExtension) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PULONG IntrStsReg; + EHCI_INTERRUPT_ENABLE IntrSts; + + DPRINT_RH("EHCI_RH_EnableIrq: ... \n"); + + IntrStsReg = &EhciExtension->OperationalRegs->HcInterruptEnable.AsULONG; + IntrSts.AsULONG = READ_REGISTER_ULONG(IntrStsReg); + + EhciExtension->InterruptMask.PortChangeInterrupt = 1; + IntrSts.PortChangeInterrupt = 1; + + if (IntrSts.Interrupt) + WRITE_REGISTER_ULONG(IntrStsReg, IntrSts.AsULONG); +} diff --git a/drivers/usb/usbehci_new/usbehci.c b/drivers/usb/usbehci_new/usbehci.c new file mode 100644 index 0000000000..bdfd889ff1 --- /dev/null +++ b/drivers/usb/usbehci_new/usbehci.c @@ -0,0 +1,3696 @@ +/* + * PROJECT: ReactOS USB EHCI Miniport Driver + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: USBEHCI main driver functions + * COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal(a)rambler.ru> + */ + +#include "usbehci.h" + +#define NDEBUG +#include <debug.h> + +#define NDEBUG_EHCI_TRACE +#include "dbg_ehci.h" + +USBPORT_REGISTRATION_PACKET RegPacket; + +static const UCHAR ClassicPeriod[8] = { + ENDPOINT_INTERRUPT_1ms - 1, + ENDPOINT_INTERRUPT_2ms - 1, + ENDPOINT_INTERRUPT_4ms - 1, + ENDPOINT_INTERRUPT_8ms - 1, + ENDPOINT_INTERRUPT_16ms - 1, + ENDPOINT_INTERRUPT_32ms - 1, + ENDPOINT_INTERRUPT_32ms - 1, + ENDPOINT_INTERRUPT_32ms - 1 +}; + +static const EHCI_PERIOD pTable[] = { + { ENDPOINT_INTERRUPT_1ms, 0x00, 0xFF }, + { ENDPOINT_INTERRUPT_2ms, 0x00, 0x55 }, + { ENDPOINT_INTERRUPT_2ms, 0x00, 0xAA }, + { ENDPOINT_INTERRUPT_4ms, 0x00, 0x11 }, + { ENDPOINT_INTERRUPT_4ms, 0x00, 0x44 }, + { ENDPOINT_INTERRUPT_4ms, 0x00, 0x22 }, + { ENDPOINT_INTERRUPT_4ms, 0x00, 0x88 }, + { ENDPOINT_INTERRUPT_8ms, 0x00, 0x01 }, + { ENDPOINT_INTERRUPT_8ms, 0x00, 0x10 }, + { ENDPOINT_INTERRUPT_8ms, 0x00, 0x04 }, + { ENDPOINT_INTERRUPT_8ms, 0x00, 0x40 }, + { ENDPOINT_INTERRUPT_8ms, 0x00, 0x02 }, + { ENDPOINT_INTERRUPT_8ms, 0x00, 0x20 }, + { ENDPOINT_INTERRUPT_8ms, 0x00, 0x08 }, + { ENDPOINT_INTERRUPT_8ms, 0x00, 0x80 }, + { ENDPOINT_INTERRUPT_16ms, 0x01, 0x01 }, + { ENDPOINT_INTERRUPT_16ms, 0x02, 0x01 }, + { ENDPOINT_INTERRUPT_16ms, 0x01, 0x10 }, + { ENDPOINT_INTERRUPT_16ms, 0x02, 0x10 }, + { ENDPOINT_INTERRUPT_16ms, 0x01, 0x04 }, + { ENDPOINT_INTERRUPT_16ms, 0x02, 0x04 }, + { ENDPOINT_INTERRUPT_16ms, 0x01, 0x40 }, + { ENDPOINT_INTERRUPT_16ms, 0x02, 0x40 }, + { ENDPOINT_INTERRUPT_16ms, 0x01, 0x02 }, + { ENDPOINT_INTERRUPT_16ms, 0x02, 0x02 }, + { ENDPOINT_INTERRUPT_16ms, 0x01, 0x20 }, + { ENDPOINT_INTERRUPT_16ms, 0x02, 0x20 }, + { ENDPOINT_INTERRUPT_16ms, 0x01, 0x08 }, + { ENDPOINT_INTERRUPT_16ms, 0x02, 0x08 }, + { ENDPOINT_INTERRUPT_16ms, 0x01, 0x80 }, + { ENDPOINT_INTERRUPT_16ms, 0x02, 0x80 }, + { ENDPOINT_INTERRUPT_32ms, 0x03, 0x01 }, + { ENDPOINT_INTERRUPT_32ms, 0x05, 0x01 }, + { ENDPOINT_INTERRUPT_32ms, 0x04, 0x01 }, + { ENDPOINT_INTERRUPT_32ms, 0x06, 0x01 }, + { ENDPOINT_INTERRUPT_32ms, 0x03, 0x10 }, + { ENDPOINT_INTERRUPT_32ms, 0x05, 0x10 }, + { ENDPOINT_INTERRUPT_32ms, 0x04, 0x10 }, + { ENDPOINT_INTERRUPT_32ms, 0x06, 0x10 }, + { ENDPOINT_INTERRUPT_32ms, 0x03, 0x04 }, + { ENDPOINT_INTERRUPT_32ms, 0x05, 0x04 }, + { ENDPOINT_INTERRUPT_32ms, 0x04, 0x04 }, + { ENDPOINT_INTERRUPT_32ms, 0x06, 0x04 }, + { ENDPOINT_INTERRUPT_32ms, 0x03, 0x40 }, + { ENDPOINT_INTERRUPT_32ms, 0x05, 0x40 }, + { ENDPOINT_INTERRUPT_32ms, 0x04, 0x40 }, + { ENDPOINT_INTERRUPT_32ms, 0x06, 0x40 }, + { ENDPOINT_INTERRUPT_32ms, 0x03, 0x02 }, + { ENDPOINT_INTERRUPT_32ms, 0x05, 0x02 }, + { ENDPOINT_INTERRUPT_32ms, 0x04, 0x02 }, + { ENDPOINT_INTERRUPT_32ms, 0x06, 0x02 }, + { ENDPOINT_INTERRUPT_32ms, 0x03, 0x20 }, + { ENDPOINT_INTERRUPT_32ms, 0x05, 0x20 }, + { ENDPOINT_INTERRUPT_32ms, 0x04, 0x20 }, + { ENDPOINT_INTERRUPT_32ms, 0x06, 0x20 }, + { ENDPOINT_INTERRUPT_32ms, 0x03, 0x08 }, + { ENDPOINT_INTERRUPT_32ms, 0x05, 0x08 }, + { ENDPOINT_INTERRUPT_32ms, 0x04, 0x08 }, + { ENDPOINT_INTERRUPT_32ms, 0x06, 0x08 }, + { ENDPOINT_INTERRUPT_32ms, 0x03, 0x80 }, + { ENDPOINT_INTERRUPT_32ms, 0x05, 0x80 }, + { ENDPOINT_INTERRUPT_32ms, 0x04, 0x80 }, + { ENDPOINT_INTERRUPT_32ms, 0x06, 0x80 }, + { 0x00, 0x00, 0x00 } +}; +C_ASSERT(RTL_NUMBER_OF(pTable) == INTERRUPT_ENDPOINTs + 1); + +static const UCHAR Balance[] = { + 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30, + 1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31 +}; +C_ASSERT(RTL_NUMBER_OF(Balance) == EHCI_FRAMES); + +static const UCHAR LinkTable[] = { + 255, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, + 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, + 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, + 30, 30, 0 +}; +C_ASSERT(RTL_NUMBER_OF(LinkTable) == INTERRUPT_ENDPOINTs + 1); + +PEHCI_HCD_TD +NTAPI +EHCI_AllocTd(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint) +{ + PEHCI_HCD_TD TD; + ULONG ix; + + DPRINT_EHCI("EHCI_AllocTd: ... \n"); + + if (EhciEndpoint->MaxTDs == 0) + { + RegPacket.UsbPortBugCheck(EhciExtension); + return NULL; + } + + TD = EhciEndpoint->FirstTD; + + for (ix = 1; TD->TdFlags & EHCI_HCD_TD_FLAG_ALLOCATED; ix++) + { + TD += 1; + + if (ix >= EhciEndpoint->MaxTDs) + { + RegPacket.UsbPortBugCheck(EhciExtension); + return NULL; + } + } + + TD->TdFlags |= EHCI_HCD_TD_FLAG_ALLOCATED; + + EhciEndpoint->RemainTDs--; + + return TD; +} + +PEHCI_HCD_QH +NTAPI +EHCI_InitializeQH(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint, + IN PEHCI_HCD_QH QH, + IN ULONG QhPA) +{ + PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties; + ULONG DeviceSpeed; + + DPRINT_EHCI("EHCI_InitializeQH: EhciEndpoint - %p, QH - %p, QhPA - %p\n", + EhciEndpoint, + QH, + QhPA); + + EndpointProperties = &EhciEndpoint->EndpointProperties; + + RtlZeroMemory(QH, sizeof(EHCI_HCD_QH)); + + ASSERT((QhPA & ~LINK_POINTER_MASK) == 0); + + QH->sqh.PhysicalAddress = QhPA; + + QH->sqh.HwQH.EndpointParams.DeviceAddress = EndpointProperties->DeviceAddress; + QH->sqh.HwQH.EndpointParams.EndpointNumber = EndpointProperties->EndpointAddress; + + DeviceSpeed = EndpointProperties->DeviceSpeed; + + switch (DeviceSpeed) + { + case UsbLowSpeed: + QH->sqh.HwQH.EndpointParams.EndpointSpeed = EHCI_QH_EP_LOW_SPEED; + break; + + case UsbFullSpeed: + QH->sqh.HwQH.EndpointParams.EndpointSpeed = EHCI_QH_EP_FULL_SPEED; + break; + + case UsbHighSpeed: + QH->sqh.HwQH.EndpointParams.EndpointSpeed = EHCI_QH_EP_HIGH_SPEED; + break; + + default: + DPRINT1("EHCI_InitializeQH: Unknown DeviceSpeed - %x\n", DeviceSpeed); + ASSERT(FALSE); + break; + } + + QH->sqh.HwQH.EndpointParams.MaximumPacketLength = EndpointProperties->MaxPacketSize; + QH->sqh.HwQH.EndpointCaps.PipeMultiplier = 1; + + if (DeviceSpeed == UsbHighSpeed) + { + QH->sqh.HwQH.EndpointCaps.HubAddr = 0; + QH->sqh.HwQH.EndpointCaps.PortNumber = 0; + } + else + { + QH->sqh.HwQH.EndpointCaps.HubAddr = EndpointProperties->HubAddr; + QH->sqh.HwQH.EndpointCaps.PortNumber = EndpointProperties->PortNumber; + + if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_CONTROL) + QH->sqh.HwQH.EndpointParams.ControlEndpointFlag = 1; + } + + QH->sqh.HwQH.NextTD = TERMINATE_POINTER; + QH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; + + QH->sqh.HwQH.Token.Status &= (UCHAR)~(EHCI_TOKEN_STATUS_ACTIVE | + EHCI_TOKEN_STATUS_HALTED); + + return QH; +} + +MPSTATUS +NTAPI +EHCI_OpenBulkOrControlEndpoint(IN PEHCI_EXTENSION EhciExtension, + IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, + IN PEHCI_ENDPOINT EhciEndpoint, + IN BOOLEAN IsControl) +{ + PEHCI_HCD_QH QH; + ULONG QhPA; + PEHCI_HCD_TD TdVA; + ULONG TdPA; + PEHCI_HCD_TD TD; + ULONG TdCount; + ULONG ix; + + DPRINT("EHCI_OpenBulkOrControlEndpoint: EhciEndpoint - %p, IsControl - %x\n", + EhciEndpoint, + IsControl); + + InitializeListHead(&EhciEndpoint->ListTDs); + + EhciEndpoint->DmaBufferVA = (PVOID)EndpointProperties->BufferVA; + EhciEndpoint->DmaBufferPA = EndpointProperties->BufferPA; + + RtlZeroMemory(EhciEndpoint->DmaBufferVA, sizeof(EHCI_HCD_TD)); + + QH = (PEHCI_HCD_QH)EhciEndpoint->DmaBufferVA + 1; + QhPA = EhciEndpoint->DmaBufferPA + sizeof(EHCI_HCD_TD); + + EhciEndpoint->FirstTD = (PEHCI_HCD_TD)(QH + 1); + + TdCount = (EndpointProperties->BufferLength - + (sizeof(EHCI_HCD_TD) + sizeof(EHCI_HCD_QH))) / + sizeof(EHCI_HCD_TD); + + if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_CONTROL) + EhciEndpoint->EndpointStatus |= USBPORT_ENDPOINT_CONTROL; + + EhciEndpoint->MaxTDs = TdCount; + EhciEndpoint->RemainTDs = TdCount; + + TdVA = EhciEndpoint->FirstTD; + TdPA = QhPA + sizeof(EHCI_HCD_QH); + + for (ix = 0; ix < TdCount; ix++) + { + DPRINT_EHCI("EHCI_OpenBulkOrControlEndpoint: TdVA - %p, TdPA - %p\n", + TdVA, + TdPA); + + RtlZeroMemory(TdVA, sizeof(EHCI_HCD_TD)); + + ASSERT((TdPA & ~LINK_POINTER_MASK) == 0); + + TdVA->PhysicalAddress = TdPA; + TdVA->EhciEndpoint = EhciEndpoint; + TdVA->EhciTransfer = NULL; + + TdPA += sizeof(EHCI_HCD_TD); + TdVA += 1; + } + + EhciEndpoint->QH = EHCI_InitializeQH(EhciExtension, + EhciEndpoint, + QH, + QhPA); + + if (IsControl) + { + QH->sqh.HwQH.EndpointParams.DataToggleControl = 1; + EhciEndpoint->HcdHeadP = NULL; + } + else + { + QH->sqh.HwQH.EndpointParams.DataToggleControl = 0; + } + + TD = EHCI_AllocTd(EhciExtension, EhciEndpoint); + + if (!TD) + return MP_STATUS_NO_RESOURCES; + + TD->TdFlags |= EHCI_HCD_TD_FLAG_DUMMY; + TD->HwTD.Token.Status &= (UCHAR)~EHCI_TOKEN_STATUS_ACTIVE; + + TD->HwTD.NextTD = TERMINATE_POINTER; + TD->HwTD.AlternateNextTD = TERMINATE_POINTER; + + TD->NextHcdTD = NULL; + TD->AltNextHcdTD = NULL; + + EhciEndpoint->HcdTailP = TD; + EhciEndpoint->HcdHeadP = TD; + + QH->sqh.HwQH.CurrentTD = TD->PhysicalAddress; + QH->sqh.HwQH.NextTD = TERMINATE_POINTER; + QH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; + + QH->sqh.HwQH.Token.Status &= (UCHAR)~EHCI_TOKEN_STATUS_ACTIVE; + QH->sqh.HwQH.Token.TransferBytes = 0; + + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_OpenInterruptEndpoint(IN PEHCI_EXTENSION EhciExtension, + IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, + IN PEHCI_ENDPOINT EhciEndpoint) +{ + PEHCI_HCD_QH QH; + ULONG QhPA; + PEHCI_HCD_TD FirstTD; + ULONG FirstTdPA; + PEHCI_HCD_TD TD; + PEHCI_HCD_TD DummyTD; + ULONG TdCount; + ULONG ix; + const EHCI_PERIOD * PeriodTable = NULL; + ULONG ScheduleOffset; + ULONG Idx = 0; + UCHAR Period; + + DPRINT("EHCI_OpenInterruptEndpoint: EhciExtension - %p, EndpointProperties - %p, EhciEndpoint - %p\n", + EhciExtension, + EndpointProperties, + EhciEndpoint); + + Period = EndpointProperties->Period; + ScheduleOffset = EndpointProperties->ScheduleOffset; + + ASSERT(Period < (INTERRUPT_ENDPOINTs + 1)); + + while (!(Period & 1)) + { + Idx++; + Period >>= 1; + } + + ASSERT(Idx < 8); + + InitializeListHead(&EhciEndpoint->ListTDs); + + if (EhciEndpoint->EndpointProperties.DeviceSpeed == UsbHighSpeed) + { + PeriodTable = &pTable[ClassicPeriod[Idx] + ScheduleOffset]; + EhciEndpoint->PeriodTable = PeriodTable; + + DPRINT("EHCI_OpenInterruptEndpoint: EhciEndpoint - %p, ScheduleMask - %X, Index - %X\n", + EhciEndpoint, + PeriodTable->ScheduleMask, + ClassicPeriod[Idx]); + + EhciEndpoint->StaticQH = EhciExtension->PeriodicHead[PeriodTable->PeriodIdx]; + } + else + { + EhciEndpoint->PeriodTable = NULL; + + DPRINT("EHCI_OpenInterruptEndpoint: EhciEndpoint - %p, Index - %X\n", + EhciEndpoint, + ClassicPeriod[Idx]); + + EhciEndpoint->StaticQH = EhciExtension->PeriodicHead[ClassicPeriod[Idx] + + ScheduleOffset]; + } + + EhciEndpoint->DmaBufferVA = (PVOID)EndpointProperties->BufferVA; + EhciEndpoint->DmaBufferPA = EndpointProperties->BufferPA; + + RtlZeroMemory((PVOID)EndpointProperties->BufferVA, sizeof(EHCI_HCD_TD)); + + QH = (PEHCI_HCD_QH)(EndpointProperties->BufferVA + sizeof(EHCI_HCD_TD)); + QhPA = EndpointProperties->BufferPA + sizeof(EHCI_HCD_TD); + + FirstTD = (PEHCI_HCD_TD)(EndpointProperties->BufferVA + + sizeof(EHCI_HCD_TD) + + sizeof(EHCI_HCD_QH)); + + FirstTdPA = EndpointProperties->BufferPA + + sizeof(EHCI_HCD_TD) + + sizeof(EHCI_HCD_QH); + + TdCount = (EndpointProperties->BufferLength - + (sizeof(EHCI_HCD_TD) + sizeof(EHCI_HCD_QH))) / + sizeof(EHCI_HCD_TD); + + ASSERT(TdCount >= EHCI_MAX_INTERRUPT_TD_COUNT + 1); + + EhciEndpoint->FirstTD = FirstTD; + EhciEndpoint->MaxTDs = TdCount; + + for (ix = 0; ix < TdCount; ix++) + { + TD = EhciEndpoint->FirstTD + ix; + + RtlZeroMemory(TD, sizeof(EHCI_HCD_TD)); + + ASSERT((FirstTdPA & ~LINK_POINTER_MASK) == 0); + + TD->PhysicalAddress = FirstTdPA; + TD->EhciEndpoint = EhciEndpoint; + TD->EhciTransfer = NULL; + + FirstTdPA += sizeof(EHCI_HCD_TD); + } + + EhciEndpoint->RemainTDs = TdCount; + + EhciEndpoint->QH = EHCI_InitializeQH(EhciExtension, + EhciEndpoint, + QH, + QhPA); + + if (EhciEndpoint->EndpointProperties.DeviceSpeed == UsbHighSpeed) + { + QH->sqh.HwQH.EndpointCaps.InterruptMask = PeriodTable->ScheduleMask; + } + else + { + QH->sqh.HwQH.EndpointCaps.InterruptMask = + EndpointProperties->InterruptScheduleMask; + + QH->sqh.HwQH.EndpointCaps.SplitCompletionMask = + EndpointProperties->SplitCompletionMask; + } + + DummyTD = EHCI_AllocTd(EhciExtension, EhciEndpoint); + + DummyTD->TdFlags |= EHCI_HCD_TD_FLAG_DUMMY; + DummyTD->NextHcdTD = NULL; + DummyTD->AltNextHcdTD = NULL; + + DummyTD->HwTD.Token.Status &= ~EHCI_TOKEN_STATUS_ACTIVE; + + DummyTD->HwTD.NextTD = TERMINATE_POINTER; + DummyTD->HwTD.AlternateNextTD = TERMINATE_POINTER; + + EhciEndpoint->HcdTailP = DummyTD; + EhciEndpoint->HcdHeadP = DummyTD; + + QH->sqh.HwQH.CurrentTD = DummyTD->PhysicalAddress; + QH->sqh.HwQH.NextTD = TERMINATE_POINTER; + QH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; + + QH->sqh.HwQH.Token.Status &= ~EHCI_TOKEN_STATUS_ACTIVE; + QH->sqh.HwQH.Token.TransferBytes = 0; + + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_OpenHsIsoEndpoint(IN PEHCI_EXTENSION EhciExtension, + IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, + IN PEHCI_ENDPOINT EhciEndpoint) +{ + DPRINT1("EHCI_OpenHsIsoEndpoint: UNIMPLEMENTED. FIXME\n"); + return MP_STATUS_NOT_SUPPORTED; +} + +MPSTATUS +NTAPI +EHCI_OpenIsoEndpoint(IN PEHCI_EXTENSION EhciExtension, + IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, + IN PEHCI_ENDPOINT EhciEndpoint) +{ + DPRINT1("EHCI_OpenIsoEndpoint: UNIMPLEMENTED. FIXME\n"); + return MP_STATUS_NOT_SUPPORTED; +} + +MPSTATUS +NTAPI +EHCI_OpenEndpoint(IN PVOID ehciExtension, + IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, + IN PVOID ehciEndpoint) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PEHCI_ENDPOINT EhciEndpoint = ehciEndpoint; + ULONG TransferType; + MPSTATUS MPStatus; + + DPRINT("EHCI_OpenEndpoint: ... \n"); + + RtlCopyMemory(&EhciEndpoint->EndpointProperties, + EndpointProperties, + sizeof(EhciEndpoint->EndpointProperties)); + + TransferType = EndpointProperties->TransferType; + + switch (TransferType) + { + case USBPORT_TRANSFER_TYPE_ISOCHRONOUS: + if (EndpointProperties->DeviceSpeed == UsbHighSpeed) + { + MPStatus = EHCI_OpenHsIsoEndpoint(EhciExtension, + EndpointProperties, + EhciEndpoint); + } + else + { + MPStatus = EHCI_OpenIsoEndpoint(EhciExtension, + EndpointProperties, + EhciEndpoint); + } + + break; + + case USBPORT_TRANSFER_TYPE_CONTROL: + MPStatus = EHCI_OpenBulkOrControlEndpoint(EhciExtension, + EndpointProperties, + EhciEndpoint, + TRUE); + break; + + case USBPORT_TRANSFER_TYPE_BULK: + MPStatus = EHCI_OpenBulkOrControlEndpoint(EhciExtension, + EndpointProperties, + EhciEndpoint, + FALSE); + break; + + case USBPORT_TRANSFER_TYPE_INTERRUPT: + MPStatus = EHCI_OpenInterruptEndpoint(EhciExtension, + EndpointProperties, + EhciEndpoint); + break; + + default: + MPStatus = MP_STATUS_NOT_SUPPORTED; + break; + } + + return MPStatus; +} + +MPSTATUS +NTAPI +EHCI_ReopenEndpoint(IN PVOID ehciExtension, + IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, + IN PVOID ehciEndpoint) +{ + PEHCI_ENDPOINT EhciEndpoint; + ULONG TransferType; + PEHCI_HCD_QH QH; + MPSTATUS MPStatus; + + EhciEndpoint = ehciEndpoint; + + TransferType = EndpointProperties->TransferType; + + DPRINT("EHCI_ReopenEndpoint: EhciEndpoint - %p, TransferType - %x\n", + EhciEndpoint, + TransferType); + + switch (TransferType) + { + case USBPORT_TRANSFER_TYPE_ISOCHRONOUS: + if (EndpointProperties->DeviceSpeed == UsbHighSpeed) + { + DPRINT1("EHCI_ReopenEndpoint: HS Iso. UNIMPLEMENTED. FIXME\n"); + MPStatus = MP_STATUS_NOT_SUPPORTED; + } + else + { + DPRINT1("EHCI_ReopenEndpoint: Iso. UNIMPLEMENTED. FIXME\n"); + MPStatus = MP_STATUS_NOT_SUPPORTED; + } + + break; + + case USBPORT_TRANSFER_TYPE_CONTROL: + case USBPORT_TRANSFER_TYPE_BULK: + case USBPORT_TRANSFER_TYPE_INTERRUPT: + RtlCopyMemory(&EhciEndpoint->EndpointProperties, + EndpointProperties, + sizeof(EhciEndpoint->EndpointProperties)); + + QH = EhciEndpoint->QH; + + QH->sqh.HwQH.EndpointParams.DeviceAddress = EndpointProperties->DeviceAddress; + QH->sqh.HwQH.EndpointParams.MaximumPacketLength = EndpointProperties->MaxPacketSize; + + QH->sqh.HwQH.EndpointCaps.HubAddr = EndpointProperties->HubAddr; + + break; + + default: + DPRINT1("EHCI_ReopenEndpoint: Unknown TransferType\n"); + MPStatus = MP_STATUS_SUCCESS; + break; + } + + return MPStatus; +} + +VOID +NTAPI +EHCI_QueryEndpointRequirements(IN PVOID ehciExtension, + IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, + IN PUSBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements) +{ + ULONG TransferType; + + DPRINT("EHCI_QueryEndpointRequirements: ... \n"); + + TransferType = EndpointProperties->TransferType; + + switch (TransferType) + { + case USBPORT_TRANSFER_TYPE_ISOCHRONOUS: + DPRINT("EHCI_QueryEndpointRequirements: IsoTransfer\n"); + + if (EndpointProperties->DeviceSpeed == UsbHighSpeed) + { + EndpointRequirements->HeaderBufferSize = EHCI_MAX_HS_ISO_HEADER_BUFFER_SIZE; + EndpointRequirements->MaxTransferSize = EHCI_MAX_HS_ISO_TRANSFER_SIZE; + } + else + { + EndpointRequirements->HeaderBufferSize = EHCI_MAX_FS_ISO_HEADER_BUFFER_SIZE; + EndpointRequirements->MaxTransferSize = EHCI_MAX_FS_ISO_TRANSFER_SIZE; + } + break; + + case USBPORT_TRANSFER_TYPE_CONTROL: + DPRINT("EHCI_QueryEndpointRequirements: ControlTransfer\n"); + EndpointRequirements->HeaderBufferSize = sizeof(EHCI_HCD_TD) + + sizeof(EHCI_HCD_QH) + + EHCI_MAX_CONTROL_TD_COUNT * sizeof(EHCI_HCD_TD); + + EndpointRequirements->MaxTransferSize = EHCI_MAX_CONTROL_TRANSFER_SIZE; + break; + + case USBPORT_TRANSFER_TYPE_BULK: + DPRINT("EHCI_QueryEndpointRequirements: BulkTransfer\n"); + EndpointRequirements->HeaderBufferSize = sizeof(EHCI_HCD_TD) + + sizeof(EHCI_HCD_QH) + + EHCI_MAX_BULK_TD_COUNT * sizeof(EHCI_HCD_TD); + + EndpointRequirements->MaxTransferSize = EHCI_MAX_BULK_TRANSFER_SIZE; + break; + + case USBPORT_TRANSFER_TYPE_INTERRUPT: + DPRINT("EHCI_QueryEndpointRequirements: InterruptTransfer\n"); + EndpointRequirements->HeaderBufferSize = sizeof(EHCI_HCD_TD) + + sizeof(EHCI_HCD_QH) + + EHCI_MAX_INTERRUPT_TD_COUNT * sizeof(EHCI_HCD_TD); + + EndpointRequirements->MaxTransferSize = EHCI_MAX_INTERRUPT_TRANSFER_SIZE; + break; + + default: + DPRINT1("EHCI_QueryEndpointRequirements: Unknown TransferType - %x\n", + TransferType); + DbgBreakPoint(); + break; + } +} + +VOID +NTAPI +EHCI_DisablePeriodicList(IN PEHCI_EXTENSION EhciExtension) +{ + PEHCI_HW_REGISTERS OperationalRegs; + EHCI_USB_COMMAND Command; + + DPRINT("EHCI_DisablePeriodicList: ... \n"); + + if (EhciExtension->Flags & EHCI_FLAGS_IDLE_SUPPORT) + { + OperationalRegs = EhciExtension->OperationalRegs; + + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + Command.PeriodicEnable = 0; + WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); + } +} + +VOID +NTAPI +EHCI_CloseEndpoint(IN PVOID ehciExtension, + IN PVOID ehciEndpoint, + IN BOOLEAN DisablePeriodic) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PEHCI_ENDPOINT EhciEndpoint = ehciEndpoint; + ULONG TransferType; + + DPRINT1("EHCI_CloseEndpoint: EhciEndpoint - %p, DisablePeriodic - %X\n", + EhciEndpoint, + DisablePeriodic); + + if (DisablePeriodic) + { + TransferType = EhciEndpoint->EndpointProperties.TransferType; + + if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS || + TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) + { + EHCI_DisablePeriodicList(EhciExtension); + } + } +} + +PEHCI_STATIC_QH +NTAPI +EHCI_GetQhForFrame(IN PEHCI_EXTENSION EhciExtension, + IN ULONG FrameIdx) +{ + //DPRINT_EHCI("EHCI_GetQhForFrame: FrameIdx - %x, Balance[FrameIdx] - %x\n", + // FrameIdx, + // Balance[FrameIdx & 0x1F]); + + return EhciExtension->PeriodicHead[Balance[FrameIdx & (EHCI_FRAMES - 1)]]; +} + +PEHCI_HCD_QH +NTAPI +EHCI_GetDummyQhForFrame(IN PEHCI_EXTENSION EhciExtension, + IN ULONG Idx) +{ + return (PEHCI_HCD_QH)((ULONG_PTR)EhciExtension->IsoDummyQHListVA + + Idx * sizeof(EHCI_HCD_QH)); +} + +VOID +NTAPI +EHCI_AlignHwStructure(IN PEHCI_EXTENSION EhciExtension, + IN PULONG PhysicalAddress, + IN PULONG_PTR VirtualAddress, + IN ULONG Alignment) +{ + ULONG PAddress; + ULONG NewPAddress; + ULONG_PTR VAddress; + + //DPRINT_EHCI("EHCI_AlignHwStructure: *PhysicalAddress - %X, *VirtualAddress - %X, Alignment - %x\n", + // *PhysicalAddress, + // *VirtualAddress, + // Alignment); + + PAddress = *PhysicalAddress; + VAddress = *VirtualAddress; + + NewPAddress = (ULONG)(ULONG_PTR)PAGE_ALIGN(*PhysicalAddress + Alignment - 1); + + if (NewPAddress != (ULONG)(ULONG_PTR)PAGE_ALIGN(*PhysicalAddress)) + { + VAddress += NewPAddress - PAddress; + PAddress = NewPAddress; + + DPRINT("EHCI_AlignHwStructure: VAddress - %X, PAddress - %X\n", + VAddress, + PAddress); + } + + *VirtualAddress = VAddress; + *PhysicalAddress = PAddress; +} + +VOID +NTAPI +EHCI_AddDummyQHs(IN PEHCI_EXTENSION EhciExtension) +{ + PEHCI_HC_RESOURCES HcResourcesVA; + PEHCI_HCD_QH DummyQH; + ULONG DummyQhPA; + EHCI_QH_EP_PARAMS EndpointParams; + EHCI_LINK_POINTER PAddress; + ULONG Frame; + + DPRINT("EHCI_AddDummyQueueHeads: EhciExtension - %p\n", EhciExtension); + + HcResourcesVA = EhciExtension->HcResourcesVA; + + DummyQH = EhciExtension->IsoDummyQHListVA; + DummyQhPA = EhciExtension->IsoDummyQHListPA; + + for (Frame = 0; Frame < EHCI_FRAME_LIST_MAX_ENTRIES; Frame++) + { + RtlZeroMemory(DummyQH, sizeof(EHCI_HCD_QH)); + + PAddress.AsULONG = HcResourcesVA->PeriodicFrameList[Frame]; + + DummyQH->sqh.HwQH.HorizontalLink.AsULONG = PAddress.AsULONG; + DummyQH->sqh.HwQH.CurrentTD = 0; + DummyQH->sqh.HwQH.NextTD = TERMINATE_POINTER; + DummyQH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; + + EndpointParams = DummyQH->sqh.HwQH.EndpointParams; + EndpointParams.DeviceAddress = 0; + EndpointParams.EndpointSpeed = 0; + EndpointParams.MaximumPacketLength = EHCI_DUMMYQH_MAX_PACKET_LENGTH; + DummyQH->sqh.HwQH.EndpointParams = EndpointParams; + + DummyQH->sqh.HwQH.EndpointCaps.AsULONG = 0; + DummyQH->sqh.HwQH.EndpointCaps.InterruptMask = 0; + DummyQH->sqh.HwQH.EndpointCaps.SplitCompletionMask = 0; + DummyQH->sqh.HwQH.EndpointCaps.PipeMultiplier = 1; + + DummyQH->sqh.HwQH.Token.Status &= (UCHAR)~EHCI_TOKEN_STATUS_ACTIVE; + + DummyQH->sqh.PhysicalAddress = DummyQhPA; + DummyQH->sqh.StaticQH = EHCI_GetQhForFrame(EhciExtension, Frame); + + PAddress.AsULONG = DummyQhPA; + PAddress.Reserved = 0; + PAddress.Type = EHCI_LINK_TYPE_QH; + + HcResourcesVA->PeriodicFrameList[Frame] = PAddress.AsULONG; + + DummyQH++; + DummyQhPA += sizeof(EHCI_HCD_QH); + } +} + +VOID +NTAPI +EHCI_InitializeInterruptSchedule(IN PEHCI_EXTENSION EhciExtension) +{ + PEHCI_STATIC_QH StaticQH; + ULONG ix; + + DPRINT("EHCI_InitializeInterruptSchedule: ... \n"); + + for (ix = 0; ix < INTERRUPT_ENDPOINTs; ix++) + { + StaticQH = EhciExtension->PeriodicHead[ix]; + + StaticQH->HwQH.EndpointParams.HeadReclamationListFlag = 0; + StaticQH->HwQH.NextTD |= TERMINATE_POINTER; + StaticQH->HwQH.Token.Status |= (UCHAR)EHCI_TOKEN_STATUS_HALTED; + } + + for (ix = 1; ix < INTERRUPT_ENDPOINTs; ix++) + { + StaticQH = EhciExtension->PeriodicHead[ix]; + + StaticQH->PrevHead = NULL; + StaticQH->NextHead = (PEHCI_HCD_QH)EhciExtension->PeriodicHead[LinkTable[ix]]; + + StaticQH->HwQH.HorizontalLink.AsULONG = + EhciExtension->PeriodicHead[LinkTable[ix]]->PhysicalAddress; + + StaticQH->HwQH.HorizontalLink.Type = EHCI_LINK_TYPE_QH; + StaticQH->HwQH.EndpointCaps.InterruptMask = 0xFF; + + StaticQH->QhFlags |= EHCI_QH_FLAG_STATIC; + + if (ix < (ENDPOINT_INTERRUPT_8ms - 1)) + StaticQH->QhFlags |= EHCI_QH_FLAG_STATIC_FAST; + } + + EhciExtension->PeriodicHead[0]->HwQH.HorizontalLink.Terminate = 1; + + EhciExtension->PeriodicHead[0]->QhFlags |= (EHCI_QH_FLAG_STATIC | + EHCI_QH_FLAG_STATIC_FAST); +} + +MPSTATUS +NTAPI +EHCI_InitializeSchedule(IN PEHCI_EXTENSION EhciExtension, + IN ULONG_PTR BaseVA, + IN ULONG BasePA) +{ + PEHCI_HW_REGISTERS OperationalRegs; + PEHCI_HC_RESOURCES HcResourcesVA; + ULONG HcResourcesPA; + PEHCI_STATIC_QH AsyncHead; + ULONG AsyncHeadPA; + PEHCI_STATIC_QH PeriodicHead; + ULONG PeriodicHeadPA; + PEHCI_STATIC_QH StaticQH; + EHCI_LINK_POINTER NextLink; + EHCI_LINK_POINTER StaticHeadPA; + ULONG Frame; + ULONG ix; + + DPRINT("EHCI_InitializeSchedule: BaseVA - %p, BasePA - %p\n", + BaseVA, + BasePA); + + OperationalRegs = EhciExtension->OperationalRegs; + + HcResourcesVA = (PEHCI_HC_RESOURCES)BaseVA; + HcResourcesPA = BasePA; + + EhciExtension->HcResourcesVA = HcResourcesVA; + EhciExtension->HcResourcesPA = BasePA; + + /* Asynchronous Schedule */ + + AsyncHead = &HcResourcesVA->AsyncHead; + AsyncHeadPA = HcResourcesPA + FIELD_OFFSET(EHCI_HC_RESOURCES, AsyncHead); + + RtlZeroMemory(AsyncHead, sizeof(EHCI_STATIC_QH)); + + NextLink.AsULONG = AsyncHeadPA; + NextLink.Type = EHCI_LINK_TYPE_QH; + + AsyncHead->HwQH.HorizontalLink = NextLink; + AsyncHead->HwQH.EndpointParams.HeadReclamationListFlag = 1; + AsyncHead->HwQH.EndpointCaps.PipeMultiplier = 1; + AsyncHead->HwQH.NextTD |= TERMINATE_POINTER; + AsyncHead->HwQH.Token.Status = (UCHAR)EHCI_TOKEN_STATUS_HALTED; + + AsyncHead->PhysicalAddress = AsyncHeadPA; + AsyncHead->PrevHead = AsyncHead->NextHead = (PEHCI_HCD_QH)AsyncHead; + + EhciExtension->AsyncHead = AsyncHead; + + /* Periodic Schedule */ + + PeriodicHead = &HcResourcesVA->PeriodicHead[0]; + PeriodicHeadPA = HcResourcesPA + FIELD_OFFSET(EHCI_HC_RESOURCES, PeriodicHead[0]); + + for (ix = 0; ix < (INTERRUPT_ENDPOINTs + 1); ix++) + { + EHCI_AlignHwStructure(EhciExtension, + &PeriodicHeadPA, + (PULONG_PTR)&PeriodicHead, + 80); + + EhciExtension->PeriodicHead[ix] = PeriodicHead; + EhciExtension->PeriodicHead[ix]->PhysicalAddress = PeriodicHeadPA; + + PeriodicHead += 1; + PeriodicHeadPA += sizeof(EHCI_STATIC_QH); + } + + EHCI_InitializeInterruptSchedule(EhciExtension); + + for (Frame = 0; Frame < EHCI_FRAME_LIST_MAX_ENTRIES; Frame++) + { + StaticQH = EHCI_GetQhForFrame(EhciExtension, Frame); + + StaticHeadPA.AsULONG = StaticQH->PhysicalAddress; + StaticHeadPA.Type = EHCI_LINK_TYPE_QH; + + //DPRINT_EHCI("EHCI_InitializeSchedule: StaticHeadPA[%x] - %X\n", + // Frame, + // StaticHeadPA); + + HcResourcesVA->PeriodicFrameList[Frame] = StaticHeadPA.AsULONG; + } + + EhciExtension->IsoDummyQHListVA = &HcResourcesVA->IsoDummyQH[0]; + EhciExtension->IsoDummyQHListPA = HcResourcesPA + FIELD_OFFSET(EHCI_HC_RESOURCES, IsoDummyQH[0]); + + EHCI_AddDummyQHs(EhciExtension); + + WRITE_REGISTER_ULONG(&OperationalRegs->PeriodicListBase, + EhciExtension->HcResourcesPA + FIELD_OFFSET(EHCI_HC_RESOURCES, PeriodicFrameList)); + + WRITE_REGISTER_ULONG(&OperationalRegs->AsyncListBase, + NextLink.AsULONG); + + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_InitializeHardware(IN PEHCI_EXTENSION EhciExtension) +{ + PEHCI_HC_CAPABILITY_REGISTERS CapabilityRegisters; + PEHCI_HW_REGISTERS OperationalRegs; + EHCI_USB_COMMAND Command; + LARGE_INTEGER EndTime; + LARGE_INTEGER CurrentTime; + EHCI_HC_STRUCTURAL_PARAMS StructuralParams; + + DPRINT("EHCI_InitializeHardware: ... \n"); + + OperationalRegs = EhciExtension->OperationalRegs; + CapabilityRegisters = EhciExtension->CapabilityRegisters; + + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + Command.Reset = 1; + WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); + + KeQuerySystemTime(&EndTime); + EndTime.QuadPart += 100 * 10000; // 100 msec + + DPRINT("EHCI_InitializeHardware: Start reset ... \n"); + + while (TRUE) + { + KeQuerySystemTime(&CurrentTime); + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + + if (Command.Reset != 1) + break; + + if (CurrentTime.QuadPart >= EndTime.QuadPart) + { + if (Command.Reset == 1) + { + DPRINT1("EHCI_InitializeHardware: Reset failed!\n"); + return MP_STATUS_HW_ERROR; + } + + break; + } + } + + DPRINT("EHCI_InitializeHardware: Reset - OK\n"); + + StructuralParams.AsULONG = READ_REGISTER_ULONG(&CapabilityRegisters->StructParameters.AsULONG); + + EhciExtension->NumberOfPorts = StructuralParams.PortCount; + EhciExtension->PortPowerControl = StructuralParams.PortPowerControl; + + DPRINT("EHCI_InitializeHardware: StructuralParams - %X\n", StructuralParams.AsULONG); + DPRINT("EHCI_InitializeHardware: PortPowerControl - %x\n", EhciExtension->PortPowerControl); + DPRINT("EHCI_InitializeHardware: N_PORTS - %x\n", EhciExtension->NumberOfPorts); + + WRITE_REGISTER_ULONG(&OperationalRegs->PeriodicListBase, 0); + WRITE_REGISTER_ULONG(&OperationalRegs->AsyncListBase, 0); + + EhciExtension->InterruptMask.AsULONG = 0; + EhciExtension->InterruptMask.Interrupt = 1; + EhciExtension->InterruptMask.ErrorInterrupt = 1; + EhciExtension->InterruptMask.PortChangeInterrupt = 0; + EhciExtension->InterruptMask.FrameListRollover = 1; + EhciExtension->InterruptMask.HostSystemError = 1; + EhciExtension->InterruptMask.InterruptOnAsyncAdvance = 1; + + return MP_STATUS_SUCCESS; +} + +UCHAR +NTAPI +EHCI_GetOffsetEECP(IN PEHCI_EXTENSION EhciExtension, + IN UCHAR CapabilityID) +{ + EHCI_LEGACY_EXTENDED_CAPABILITY LegacyCapability; + EHCI_HC_CAPABILITY_PARAMS CapParameters; + UCHAR OffsetEECP; + + DPRINT("EHCI_GetOffsetEECP: CapabilityID - %x\n", CapabilityID); + + CapParameters = EhciExtension->CapabilityRegisters->CapParameters; + + OffsetEECP = CapParameters.ExtCapabilitiesPointer; + + if (!OffsetEECP) + return 0; + + while (TRUE) + { + RegPacket.UsbPortReadWriteConfigSpace(EhciExtension, + TRUE, + &LegacyCapability.AsULONG, + OffsetEECP, + sizeof(LegacyCapability)); + + DPRINT("EHCI_GetOffsetEECP: OffsetEECP - %x\n", OffsetEECP); + + if (LegacyCapability.CapabilityID == CapabilityID) + break; + + OffsetEECP = LegacyCapability.NextCapabilityPointer; + + if (!OffsetEECP) + return 0; + } + + return OffsetEECP; +} + +MPSTATUS +NTAPI +EHCI_TakeControlHC(IN PEHCI_EXTENSION EhciExtension) +{ + LARGE_INTEGER EndTime; + LARGE_INTEGER CurrentTime; + EHCI_LEGACY_EXTENDED_CAPABILITY LegacyCapability; + UCHAR OffsetEECP; + + DPRINT("EHCI_TakeControlHC: EhciExtension - %p\n", EhciExtension); + + OffsetEECP = EHCI_GetOffsetEECP(EhciExtension, 1); + + if (OffsetEECP == 0) + return MP_STATUS_SUCCESS; + + DPRINT("EHCI_TakeControlHC: OffsetEECP - %X\n", OffsetEECP); + + RegPacket.UsbPortReadWriteConfigSpace(EhciExtension, + TRUE, + &LegacyCapability.AsULONG, + OffsetEECP, + sizeof(LegacyCapability)); + + if (LegacyCapability.BiosOwnedSemaphore == 0) + return MP_STATUS_SUCCESS; + + LegacyCapability.OsOwnedSemaphore = 1; + + RegPacket.UsbPortReadWriteConfigSpace(EhciExtension, + FALSE, + &LegacyCapability.AsULONG, + OffsetEECP, + sizeof(LegacyCapability)); + + KeQuerySystemTime(&EndTime); + EndTime.QuadPart += 100 * 10000; + + do + { + RegPacket.UsbPortReadWriteConfigSpace(EhciExtension, + TRUE, + &LegacyCapability.AsULONG, + OffsetEECP, + sizeof(LegacyCapability)); + KeQuerySystemTime(&CurrentTime); + + if (LegacyCapability.BiosOwnedSemaphore) + { + DPRINT("EHCI_TakeControlHC: Ownership is ok\n"); + break; + } + } + while (CurrentTime.QuadPart <= EndTime.QuadPart); + + return MP_STATUS_SUCCESS; +} + +VOID +NTAPI +EHCI_GetRegistryParameters(IN PEHCI_EXTENSION EhciExtension) +{ + DPRINT1("EHCI_GetRegistryParameters: UNIMPLEMENTED. FIXME\n"); +} + +MPSTATUS +NTAPI +EHCI_StartController(IN PVOID ehciExtension, + IN PUSBPORT_RESOURCES Resources) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PEHCI_HC_CAPABILITY_REGISTERS CapabilityRegisters; + PEHCI_HW_REGISTERS OperationalRegs; + MPSTATUS MPStatus; + EHCI_USB_COMMAND Command; + UCHAR CapabilityRegLength; + UCHAR Fladj; + + DPRINT("EHCI_StartController: ... \n"); + + if ((Resources->ResourcesTypes & (USBPORT_RESOURCES_MEMORY | USBPORT_RESOURCES_INTERRUPT)) != + (USBPORT_RESOURCES_MEMORY | USBPORT_RESOURCES_INTERRUPT)) + { + DPRINT1("EHCI_StartController: Resources->ResourcesTypes - %x\n", + Resources->ResourcesTypes); + + return MP_STATUS_ERROR; + } + + CapabilityRegisters = (PEHCI_HC_CAPABILITY_REGISTERS)Resources->ResourceBase; + EhciExtension->CapabilityRegisters = CapabilityRegisters; + + CapabilityRegLength = READ_REGISTER_UCHAR(&CapabilityRegisters->RegistersLength); + + OperationalRegs = (PEHCI_HW_REGISTERS)((ULONG_PTR)CapabilityRegisters + + CapabilityRegLength); + + EhciExtension->OperationalRegs = OperationalRegs; + + DPRINT("EHCI_StartController: CapabilityRegisters - %p\n", CapabilityRegisters); + DPRINT("EHCI_StartController: OperationalRegs - %p\n", OperationalRegs); + + RegPacket.UsbPortReadWriteConfigSpace(EhciExtension, + TRUE, + &Fladj, + EHCI_FLADJ_PCI_CONFIG_OFFSET, + sizeof(Fladj)); + + EhciExtension->FrameLengthAdjustment = Fladj; + + EHCI_GetRegistryParameters(EhciExtension); + + MPStatus = EHCI_TakeControlHC(EhciExtension); + + if (MPStatus) + { + DPRINT1("EHCI_StartController: Unsuccessful TakeControlHC()\n"); + return MPStatus; + } + + MPStatus = EHCI_InitializeHardware(EhciExtension); + + if (MPStatus) + { + DPRINT1("EHCI_StartController: Unsuccessful InitializeHardware()\n"); + return MPStatus; + } + + MPStatus = EHCI_InitializeSchedule(EhciExtension, + Resources->StartVA, + Resources->StartPA); + + if (MPStatus) + { + DPRINT1("EHCI_StartController: Unsuccessful InitializeSchedule()\n"); + return MPStatus; + } + + RegPacket.UsbPortReadWriteConfigSpace(EhciExtension, + TRUE, + &Fladj, + EHCI_FLADJ_PCI_CONFIG_OFFSET, + sizeof(Fladj)); + + if (Fladj != EhciExtension->FrameLengthAdjustment) + { + Fladj = EhciExtension->FrameLengthAdjustment; + + RegPacket.UsbPortReadWriteConfigSpace(EhciExtension, + FALSE, // write + &Fladj, + EHCI_FLADJ_PCI_CONFIG_OFFSET, + sizeof(Fladj)); + } + + /* Port routing control logic default-routes all ports to this HC */ + EhciExtension->PortRoutingControl = EHCI_CONFIG_FLAG_CONFIGURED; + WRITE_REGISTER_ULONG(&OperationalRegs->ConfigFlag, + EhciExtension->PortRoutingControl); + + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + Command.InterruptThreshold = 1; // one micro-frame + WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); + + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + Command.Run = 1; // execution of the schedule + WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); + + EhciExtension->IsStarted = TRUE; + + if (Resources->IsChirpHandled) + { + ULONG Port; + + for (Port = 1; Port <= EhciExtension->NumberOfPorts; Port++) + { + EHCI_RH_SetFeaturePortPower(EhciExtension, Port); + } + + RegPacket.UsbPortWait(EhciExtension, 200); + + for (Port = 1; Port <= EhciExtension->NumberOfPorts; Port++) + { + EHCI_RH_ChirpRootPort(EhciExtension, Port++); + } + } + + return MPStatus; +} + +VOID +NTAPI +EHCI_StopController(IN PVOID ehciExtension, + IN BOOLEAN DisableInterrupts) +{ + DPRINT1("EHCI_StopController: UNIMPLEMENTED. FIXME\n"); +} + +VOID +NTAPI +EHCI_SuspendController(IN PVOID ehciExtension) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PEHCI_HW_REGISTERS OperationalRegs; + EHCI_USB_COMMAND Command; + EHCI_USB_STATUS Status; + EHCI_INTERRUPT_ENABLE IntrEn; + ULONG ix; + + DPRINT("EHCI_SuspendController: ... \n"); + + OperationalRegs = EhciExtension->OperationalRegs; + + EhciExtension->BackupPeriodiclistbase = READ_REGISTER_ULONG(&OperationalRegs->PeriodicListBase); + EhciExtension->BackupAsynclistaddr = READ_REGISTER_ULONG(&OperationalRegs->AsyncListBase); + EhciExtension->BackupCtrlDSSegment = READ_REGISTER_ULONG(&OperationalRegs->SegmentSelector); + EhciExtension->BackupUSBCmd = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + Command.InterruptAdvanceDoorbell = 0; + WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); + + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + Command.Run = 0; + WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); + + KeStallExecutionProcessor(125); + + Status.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG); + + Status.HCHalted = 0; + Status.Reclamation = 0; + Status.PeriodicStatus = 0; + Status.AsynchronousStatus = 0; + + if (Status.AsULONG) + WRITE_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG, Status.AsULONG); + + WRITE_REGISTER_ULONG(&OperationalRegs->HcInterruptEnable.AsULONG, 0); + + for (ix = 0; ix < 10; ix++) + { + Status.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG); + + if (Status.HCHalted) + break; + + RegPacket.UsbPortWait(EhciExtension, 1); + } + + if (!Status.HCHalted) + DbgBreakPoint(); + + IntrEn.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcInterruptEnable.AsULONG); + IntrEn.PortChangeInterrupt = 1; + WRITE_REGISTER_ULONG(&OperationalRegs->HcInterruptEnable.AsULONG, IntrEn.AsULONG); + + EhciExtension->Flags |= EHCI_FLAGS_CONTROLLER_SUSPEND; +} + +MPSTATUS +NTAPI +EHCI_ResumeController(IN PVOID ehciExtension) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PEHCI_HW_REGISTERS OperationalRegs; + ULONG RoutingControl; + EHCI_USB_COMMAND Command; + + DPRINT("EHCI_ResumeController: ... \n"); + + OperationalRegs = EhciExtension->OperationalRegs; + + RoutingControl = EhciExtension->PortRoutingControl; + + if (!(RoutingControl & EHCI_CONFIG_FLAG_CONFIGURED)) + { + EhciExtension->PortRoutingControl = RoutingControl | EHCI_CONFIG_FLAG_CONFIGURED; + WRITE_REGISTER_ULONG(&OperationalRegs->ConfigFlag, + EhciExtension->PortRoutingControl); + + return MP_STATUS_HW_ERROR; + } + + WRITE_REGISTER_ULONG(&OperationalRegs->SegmentSelector, + EhciExtension->BackupCtrlDSSegment); + + WRITE_REGISTER_ULONG(&OperationalRegs->PeriodicListBase, + EhciExtension->BackupPeriodiclistbase); + + WRITE_REGISTER_ULONG(&OperationalRegs->AsyncListBase, + EhciExtension->BackupAsynclistaddr); + + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + + Command.AsULONG = Command.AsULONG ^ EhciExtension->BackupUSBCmd; + + Command.Reset = 0; + Command.FrameListSize = 0; + Command.InterruptAdvanceDoorbell = 0; + Command.LightResetHC = 0; + Command.AsynchronousParkModeCount = 0; + Command.AsynchronousParkModeEnable = 0; + + Command.Run = 1; + + WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, + Command.AsULONG); + + WRITE_REGISTER_ULONG(&OperationalRegs->HcInterruptEnable.AsULONG, + EhciExtension->InterruptMask.AsULONG); + + EhciExtension->Flags &= ~EHCI_FLAGS_CONTROLLER_SUSPEND; + + return MP_STATUS_SUCCESS; +} + +BOOLEAN +NTAPI +EHCI_HardwarePresent(IN PEHCI_EXTENSION EhciExtension, + IN BOOLEAN IsInvalidateController) +{ + PEHCI_HW_REGISTERS OperationalRegs = EhciExtension->OperationalRegs; + + if (READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG) != -1) + return TRUE; + + DPRINT1("EHCI_HardwarePresent: IsInvalidateController - %x\n", + IsInvalidateController); + + if (!IsInvalidateController) + return FALSE; + + RegPacket.UsbPortInvalidateController(EhciExtension, + USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE); + return FALSE; +} + +BOOLEAN +NTAPI +EHCI_InterruptService(IN PVOID ehciExtension) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PEHCI_HW_REGISTERS OperationalRegs; + BOOLEAN Result = FALSE; + EHCI_USB_STATUS IntrSts; + EHCI_INTERRUPT_ENABLE IntrEn; + EHCI_INTERRUPT_ENABLE iStatus; + EHCI_USB_COMMAND Command; + ULONG FrameIndex; + + OperationalRegs = EhciExtension->OperationalRegs; + + DPRINT_EHCI("EHCI_InterruptService: ... \n"); + + Result = EHCI_HardwarePresent(EhciExtension, FALSE); + + if (!Result) + return FALSE; + + IntrEn.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcInterruptEnable.AsULONG); + IntrSts.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG); + + iStatus.AsULONG = (IntrEn.AsULONG & IntrSts.AsULONG) & EHCI_INTERRUPT_MASK; + + if (!iStatus.AsULONG) + return FALSE; + + EhciExtension->InterruptStatus = iStatus; + + WRITE_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG, iStatus.AsULONG); + + if (iStatus.HostSystemError) + { + EhciExtension->HcSystemErrors++; + + if (EhciExtension->HcSystemErrors < EHCI_MAX_HC_SYSTEM_ERRORS) + { + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + Command.Run = 1; + WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); + } + } + + FrameIndex = READ_REGISTER_ULONG(&OperationalRegs->FrameIndex) / EHCI_MICROFRAMES; + FrameIndex &= EHCI_FRINDEX_FRAME_MASK; + + if ((FrameIndex ^ EhciExtension->FrameIndex) & EHCI_FRAME_LIST_MAX_ENTRIES) + { + EhciExtension->FrameHighPart += 2 * EHCI_FRAME_LIST_MAX_ENTRIES; + + EhciExtension->FrameHighPart -= (FrameIndex ^ EhciExtension->FrameHighPart) & + EHCI_FRAME_LIST_MAX_ENTRIES; + } + + EhciExtension->FrameIndex = FrameIndex; + + return TRUE; +} + +VOID +NTAPI +EHCI_InterruptDpc(IN PVOID ehciExtension, + IN BOOLEAN EnableInterrupts) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PEHCI_HW_REGISTERS OperationalRegs; + EHCI_INTERRUPT_ENABLE iStatus; + + OperationalRegs = EhciExtension->OperationalRegs; + + DPRINT_EHCI("EHCI_InterruptDpc: [%p] EnableInterrupts - %x\n", + EhciExtension, EnableInterrupts); + + iStatus = EhciExtension->InterruptStatus; + EhciExtension->InterruptStatus.AsULONG = 0; + + if (iStatus.Interrupt == 1 || + iStatus.ErrorInterrupt == 1 || + iStatus.InterruptOnAsyncAdvance == 1) + { + DPRINT_EHCI("EHCI_InterruptDpc: [%p] InterruptStatus - %X\n", EhciExtension, iStatus.AsULONG); + RegPacket.UsbPortInvalidateEndpoint(EhciExtension, NULL); + } + + if (iStatus.PortChangeInterrupt == 1) + { + DPRINT_EHCI("EHCI_InterruptDpc: [%p] PortChangeInterrupt\n", EhciExtension); + RegPacket.UsbPortInvalidateRootHub(EhciExtension); + } + + if (EnableInterrupts) + { + WRITE_REGISTER_ULONG(&OperationalRegs->HcInterruptEnable.AsULONG, + EhciExtension->InterruptMask.AsULONG); + } +} + +ULONG +NTAPI +EHCI_MapAsyncTransferToTd(IN PEHCI_EXTENSION EhciExtension, + IN ULONG MaxPacketSize, + IN ULONG TransferedLen, + IN PULONG DataToggle, + IN PEHCI_TRANSFER EhciTransfer, + IN PEHCI_HCD_TD TD, + IN PUSBPORT_SCATTER_GATHER_LIST SgList) +{ + PUSBPORT_TRANSFER_PARAMETERS TransferParameters; + PUSBPORT_SCATTER_GATHER_ELEMENT SgElement; + ULONG SgIdx; + ULONG LengthThisTD; + ULONG ix; + ULONG SgRemain; + ULONG DiffLength; + ULONG NumPackets; + + DPRINT_EHCI("EHCI_MapAsyncTransferToTd: EhciTransfer - %p, TD - %p, TransferedLen - %x, MaxPacketSize - %x, DataToggle - %x\n", + EhciTransfer, + TD, + TransferedLen, + MaxPacketSize, + DataToggle); + + TransferParameters = EhciTransfer->TransferParameters; + + SgElement = &SgList->SgElement[0]; + + for (SgIdx = 0; SgIdx < SgList->SgElementCount; SgIdx++) + { + if (TransferedLen >= SgElement->SgOffset && + TransferedLen < SgElement->SgOffset + SgElement->SgTransferLength) + { + break; + } + + SgElement += 1; + } + + SgRemain = SgList->SgElementCount - SgIdx; + + if (SgRemain > EHCI_MAX_QTD_BUFFER_PAGES) + { + TD->HwTD.Buffer[0] = SgList->SgElement[SgIdx].SgPhysicalAddress.LowPart - + SgList->SgElement[SgIdx].SgOffset + + TransferedLen; + + LengthThisTD = EHCI_MAX_QTD_BUFFER_PAGES * PAGE_SIZE - + (TD->HwTD.Buffer[0] & (PAGE_SIZE - 1)); + + for (ix = 1; ix < EHCI_MAX_QTD_BUFFER_PAGES; ix++) + { + TD->HwTD.Buffer[ix] = SgList->SgElement[SgIdx + ix].SgPhysicalAddress.LowPart; + } + + NumPackets = LengthThisTD / MaxPacketSize; + DiffLength = LengthThisTD - MaxPacketSize * (LengthThisTD / MaxPacketSize); + + if (LengthThisTD != MaxPacketSize * (LengthThisTD / MaxPacketSize)) + LengthThisTD -= DiffLength; + + if (DataToggle && (NumPackets & 1)) + *DataToggle = !(*DataToggle); + } + else + { + LengthThisTD = TransferParameters->TransferBufferLength - TransferedLen; + + TD->HwTD.Buffer[0] = TransferedLen + + SgList->SgElement[SgIdx].SgPhysicalAddress.LowPart - + SgList->SgElement[SgIdx].SgOffset; + + for (ix = 1; ix < EHCI_MAX_QTD_BUFFER_PAGES; ix++) + { + if ((SgIdx + ix) >= SgList->SgElementCount) + break; + + TD->HwTD.Buffer[ix] = SgList->SgElement[SgIdx + ix].SgPhysicalAddress.LowPart; + } + } + + TD->HwTD.Token.TransferBytes = LengthThisTD; + TD->LengthThisTD = LengthThisTD; + + return LengthThisTD + TransferedLen; +} + +VOID +NTAPI +EHCI_EnableAsyncList(IN PEHCI_EXTENSION EhciExtension) +{ + PEHCI_HW_REGISTERS OperationalRegs; + EHCI_USB_COMMAND UsbCmd; + + DPRINT_EHCI("EHCI_EnableAsyncList: ... \n"); + + OperationalRegs = EhciExtension->OperationalRegs; + + UsbCmd.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + UsbCmd.AsynchronousEnable = 1; + WRITE_REGISTER_ULONG((&OperationalRegs->HcCommand.AsULONG), UsbCmd.AsULONG); +} + +VOID +NTAPI +EHCI_DisableAsyncList(IN PEHCI_EXTENSION EhciExtension) +{ + PEHCI_HW_REGISTERS OperationalRegs; + EHCI_USB_COMMAND UsbCmd; + + DPRINT("EHCI_DisableAsyncList: ... \n"); + + OperationalRegs = EhciExtension->OperationalRegs; + + UsbCmd.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + UsbCmd.AsynchronousEnable = 0; + WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, UsbCmd.AsULONG); +} + +VOID +NTAPI +EHCI_EnablePeriodicList(IN PEHCI_EXTENSION EhciExtension) +{ + PEHCI_HW_REGISTERS OperationalRegs; + EHCI_USB_COMMAND Command; + + DPRINT("EHCI_EnablePeriodicList: ... \n"); + + OperationalRegs = EhciExtension->OperationalRegs; + + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + Command.PeriodicEnable = 1; + WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); +} + +VOID +NTAPI +EHCI_FlushAsyncCache(IN PEHCI_EXTENSION EhciExtension) +{ + PEHCI_HW_REGISTERS OperationalRegs; + EHCI_USB_COMMAND Command; + EHCI_USB_STATUS Status; + LARGE_INTEGER CurrentTime; + LARGE_INTEGER EndTime; + EHCI_USB_COMMAND Cmd; + + DPRINT_EHCI("EHCI_FlushAsyncCache: EhciExtension - %p\n", EhciExtension); + + OperationalRegs = EhciExtension->OperationalRegs; + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + Status.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG); + + if (!Status.AsynchronousStatus && !Command.AsynchronousEnable) + return; + + if (Status.AsynchronousStatus && !Command.AsynchronousEnable) + { + KeQuerySystemTime(&EndTime); + EndTime.QuadPart += 100 * 10000; //100 ms + + do + { + Status.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG); + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + KeQuerySystemTime(&CurrentTime); + + if (CurrentTime.QuadPart > EndTime.QuadPart) + RegPacket.UsbPortBugCheck(EhciExtension); + } + while (Status.AsynchronousStatus && Command.AsULONG != -1 && Command.Run); + + return; + } + + if (!Status.AsynchronousStatus && Command.AsynchronousEnable) + { + KeQuerySystemTime(&EndTime); + EndTime.QuadPart += 100 * 10000; //100 ms + + do + { + Status.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG); + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + KeQuerySystemTime(&CurrentTime); + } + while (!Status.AsynchronousStatus && Command.AsULONG != -1 && Command.Run); + } + + Command.InterruptAdvanceDoorbell = 1; + WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); + + KeQuerySystemTime(&EndTime); + EndTime.QuadPart += 100 * 10000; //100 ms + + Cmd.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + + if (Cmd.InterruptAdvanceDoorbell) + { + while (Cmd.Run) + { + if (Cmd.AsULONG == -1) + break; + + KeStallExecutionProcessor(1); + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + KeQuerySystemTime(&CurrentTime); + + if (!Command.InterruptAdvanceDoorbell) + break; + + Cmd = Command; + } + } + + /* InterruptOnAsyncAdvance */ + WRITE_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG, 0x20); +} + +VOID +NTAPI +EHCI_LockQH(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_HCD_QH QH, + IN ULONG TransferType) +{ + PEHCI_HCD_QH PrevQH; + PEHCI_HCD_QH NextQH; + ULONG QhPA; + ULONG FrameIndexReg; + PEHCI_HW_REGISTERS OperationalRegs; + EHCI_USB_COMMAND Command; + + DPRINT_EHCI("EHCI_LockQH: QH - %p, TransferType - %x\n", + QH, + TransferType); + + OperationalRegs = EhciExtension->OperationalRegs; + + ASSERT((QH->sqh.QhFlags & EHCI_QH_FLAG_UPDATING) == 0); + ASSERT(EhciExtension->LockQH == NULL); + + PrevQH = QH->sqh.PrevHead; + QH->sqh.QhFlags |= EHCI_QH_FLAG_UPDATING; + + ASSERT(PrevQH); + + NextQH = QH->sqh.NextHead; + + EhciExtension->PrevQH = PrevQH; + EhciExtension->NextQH = NextQH; + EhciExtension->LockQH = QH; + + if (NextQH) + { + QhPA = NextQH->sqh.PhysicalAddress; + QhPA &= LINK_POINTER_MASK + TERMINATE_POINTER; + QhPA |= (EHCI_LINK_TYPE_QH << 1); + } + else + { + QhPA = TERMINATE_POINTER; + } + + PrevQH->sqh.HwQH.HorizontalLink.AsULONG = QhPA; + + FrameIndexReg = READ_REGISTER_ULONG(&OperationalRegs->FrameIndex); + + if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) + { + do + { + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + } + while (READ_REGISTER_ULONG(&OperationalRegs->FrameIndex) == + FrameIndexReg && (Command.AsULONG != -1) && Command.Run); + } + else + { + EHCI_FlushAsyncCache(EhciExtension); + } +} + +VOID +NTAPI +EHCI_UnlockQH(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_HCD_QH QH) +{ + ULONG QhPA; + + DPRINT_EHCI("EHCI_UnlockQH: QH - %p\n", QH); + + ASSERT(QH->sqh.QhFlags & EHCI_QH_FLAG_UPDATING); + ASSERT(EhciExtension->LockQH); + ASSERT(EhciExtension->LockQH == QH); + + QH->sqh.QhFlags &= ~EHCI_QH_FLAG_UPDATING; + + EhciExtension->LockQH = NULL; + + QhPA = QH->sqh.PhysicalAddress; + QhPA &= LINK_POINTER_MASK + TERMINATE_POINTER; + QhPA |= (EHCI_LINK_TYPE_QH << 1); + + EhciExtension->PrevQH->sqh.HwQH.HorizontalLink.AsULONG = QhPA; +} + +VOID +NTAPI +EHCI_LinkTransferToQueue(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint, + IN PEHCI_HCD_TD NextTD) +{ + PEHCI_HCD_QH QH; + PEHCI_HCD_TD TD; + PEHCI_TRANSFER Transfer; + PEHCI_HCD_TD LinkTD; + BOOLEAN IsPresent; + ULONG ix; + + DPRINT_EHCI("EHCI_LinkTransferToQueue: EhciEndpoint - %p, NextTD - %p\n", + EhciEndpoint, + NextTD); + + ASSERT(EhciEndpoint->HcdHeadP != NULL); + IsPresent = EHCI_HardwarePresent(EhciExtension, 0); + + QH = EhciEndpoint->QH; + TD = EhciEndpoint->HcdHeadP; + + if (TD == EhciEndpoint->HcdTailP) + { + if (IsPresent) + { + EHCI_LockQH(EhciExtension, + QH, + EhciEndpoint->EndpointProperties.TransferType); + } + + QH->sqh.HwQH.CurrentTD = EhciEndpoint->DmaBufferPA; + QH->sqh.HwQH.NextTD = NextTD->PhysicalAddress; + QH->sqh.HwQH.AlternateNextTD = NextTD->HwTD.AlternateNextTD; + + QH->sqh.HwQH.Token.Status = (UCHAR)~(EHCI_TOKEN_STATUS_ACTIVE | + EHCI_TOKEN_STATUS_HALTED); + + QH->sqh.HwQH.Token.TransferBytes = 0; + + if (IsPresent) + EHCI_UnlockQH(EhciExtension, QH); + + EhciEndpoint->HcdHeadP = NextTD; + } + else + { + DPRINT_EHCI("EHCI_LinkTransferToQueue: TD - %p, HcdTailP - %p\n", + EhciEndpoint->HcdHeadP, + EhciEndpoint->HcdTailP); + + LinkTD = EhciEndpoint->HcdHeadP; + + while (TD != EhciEndpoint->HcdTailP) + { + LinkTD = TD; + TD = TD->NextHcdTD; + } + + ASSERT(LinkTD != EhciEndpoint->HcdTailP); + + Transfer = LinkTD->EhciTransfer; + + TD = EhciEndpoint->FirstTD; + + for (ix = 0; ix < EhciEndpoint->MaxTDs; ix++) + { + if (TD->EhciTransfer == Transfer) + { + TD->AltNextHcdTD = NextTD; + TD->HwTD.AlternateNextTD = NextTD->PhysicalAddress; + } + + TD += 1; + } + + LinkTD->HwTD.NextTD = NextTD->PhysicalAddress; + LinkTD->NextHcdTD = NextTD; + + if (QH->sqh.HwQH.CurrentTD == LinkTD->PhysicalAddress) + { + QH->sqh.HwQH.NextTD = NextTD->PhysicalAddress; + QH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; + } + } +} + +MPSTATUS +NTAPI +EHCI_ControlTransfer(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint, + IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, + IN PEHCI_TRANSFER EhciTransfer, + IN PUSBPORT_SCATTER_GATHER_LIST SgList) +{ + PEHCI_HCD_TD FirstTD; + PEHCI_HCD_TD LastTD; + PEHCI_HCD_TD TD; + PEHCI_HCD_TD PrevTD; + PEHCI_HCD_TD LinkTD; + ULONG TransferedLen = 0; + EHCI_TD_TOKEN Token; + ULONG DataToggle = 1; + + DPRINT_EHCI("EHCI_ControlTransfer: EhciEndpoint - %p, EhciTransfer - %p\n", + EhciEndpoint, + EhciTransfer); + + if (EhciEndpoint->RemainTDs < EHCI_MAX_CONTROL_TD_COUNT) + return MP_STATUS_FAILURE; + + EhciExtension->PendingTransfers++; + EhciEndpoint->PendingTDs++; + + EhciTransfer->TransferOnAsyncList = 1; + + FirstTD = EHCI_AllocTd(EhciExtension, EhciEndpoint); + + if (!FirstTD) + { + RegPacket.UsbPortBugCheck(EhciExtension); + return MP_STATUS_FAILURE; + } + + EhciTransfer->PendingTDs++; + + FirstTD->TdFlags |= EHCI_HCD_TD_FLAG_PROCESSED; + FirstTD->EhciTransfer = EhciTransfer; + + FirstTD->HwTD.Buffer[0] = FirstTD->PhysicalAddress + FIELD_OFFSET(EHCI_HCD_TD, SetupPacket); + FirstTD->HwTD.Buffer[1] = 0; + FirstTD->HwTD.Buffer[2] = 0; + FirstTD->HwTD.Buffer[3] = 0; + FirstTD->HwTD.Buffer[4] = 0; + + FirstTD->NextHcdTD = NULL; + + FirstTD->HwTD.NextTD = TERMINATE_POINTER; + FirstTD->HwTD.AlternateNextTD = TERMINATE_POINTER; + + FirstTD->HwTD.Token.AsULONG = 0; + FirstTD->HwTD.Token.ErrorCounter = 3; + FirstTD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_SETUP; + FirstTD->HwTD.Token.Status = (UCHAR)EHCI_TOKEN_STATUS_ACTIVE; + FirstTD->HwTD.Token.TransferBytes = sizeof(FirstTD->SetupPacket); + + RtlCopyMemory(&FirstTD->SetupPacket, + &TransferParameters->SetupPacket, + sizeof(FirstTD->SetupPacket)); + + LastTD = EHCI_AllocTd(EhciExtension, EhciEndpoint); + + if (!LastTD) + { + RegPacket.UsbPortBugCheck(EhciExtension); + return MP_STATUS_FAILURE; + } + + EhciTransfer->PendingTDs++; + + LastTD->TdFlags |= EHCI_HCD_TD_FLAG_PROCESSED; + LastTD->EhciTransfer = EhciTransfer; + + LastTD->HwTD.Buffer[0] = 0; + LastTD->HwTD.Buffer[1] = 0; + LastTD->HwTD.Buffer[2] = 0; + LastTD->HwTD.Buffer[3] = 0; + LastTD->HwTD.Buffer[4] = 0; + + LastTD->NextHcdTD = NULL; + LastTD->HwTD.NextTD = TERMINATE_POINTER; + LastTD->HwTD.AlternateNextTD = TERMINATE_POINTER; + + LastTD->HwTD.Token.AsULONG = 0; + LastTD->HwTD.Token.ErrorCounter = 3; + + FirstTD->AltNextHcdTD = LastTD; + FirstTD->HwTD.AlternateNextTD = LastTD->PhysicalAddress; + + PrevTD = FirstTD; + LinkTD = FirstTD; + + while (TransferedLen < TransferParameters->TransferBufferLength) + { + TD = EHCI_AllocTd(EhciExtension, EhciEndpoint); + + if (!TD) + { + RegPacket.UsbPortBugCheck(EhciExtension); + return MP_STATUS_FAILURE; + } + + LinkTD = TD; + + EhciTransfer->PendingTDs++; + + TD->TdFlags |= EHCI_HCD_TD_FLAG_PROCESSED; + TD->EhciTransfer = EhciTransfer; + + TD->HwTD.Buffer[0] = 0; + TD->HwTD.Buffer[1] = 0; + TD->HwTD.Buffer[2] = 0; + TD->HwTD.Buffer[3] = 0; + TD->HwTD.Buffer[4] = 0; + + TD->NextHcdTD = NULL; + + TD->HwTD.NextTD = TERMINATE_POINTER; + TD->HwTD.AlternateNextTD = TERMINATE_POINTER; + + TD->HwTD.Token.AsULONG = 0; + TD->HwTD.Token.ErrorCounter = 3; + + PrevTD->NextHcdTD = TD; + PrevTD->HwTD.NextTD = TD->PhysicalAddress; + + if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) + TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_IN; + else + TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_OUT; + + TD->HwTD.Token.DataToggle = DataToggle; + TD->HwTD.Token.Status = (UCHAR)EHCI_TOKEN_STATUS_ACTIVE; + + if (DataToggle) + TD->HwTD.Token.DataToggle = 1; + else + TD->HwTD.Token.DataToggle = 0; + + TD->AltNextHcdTD = LastTD; + TD->HwTD.AlternateNextTD = LastTD->PhysicalAddress; + + TransferedLen = EHCI_MapAsyncTransferToTd(EhciExtension, + EhciEndpoint->EndpointProperties.MaxPacketSize, + TransferedLen, + &DataToggle, + EhciTransfer, + TD, + SgList); + + PrevTD = TD; + } + + LinkTD->NextHcdTD = LastTD; + LinkTD->HwTD.NextTD = LastTD->PhysicalAddress; + + LastTD->HwTD.Buffer[0] = 0; + LastTD->LengthThisTD = 0; + + Token.AsULONG = 0; + Token.Status = (UCHAR)EHCI_TOKEN_STATUS_ACTIVE; + Token.InterruptOnComplete = 1; + Token.DataToggle = 1; + + if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) + Token.PIDCode = EHCI_TD_TOKEN_PID_OUT; + else + Token.PIDCode = EHCI_TD_TOKEN_PID_IN; + + LastTD->HwTD.Token = Token; + + LastTD->NextHcdTD = EhciEndpoint->HcdTailP; + LastTD->HwTD.NextTD = EhciEndpoint->HcdTailP->PhysicalAddress; + + EHCI_EnableAsyncList(EhciExtension); + EHCI_LinkTransferToQueue(EhciExtension, EhciEndpoint, FirstTD); + + ASSERT(EhciEndpoint->HcdTailP->NextHcdTD == NULL); + ASSERT(EhciEndpoint->HcdTailP->AltNextHcdTD == NULL); + + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_BulkTransfer(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint, + IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, + IN PEHCI_TRANSFER EhciTransfer, + IN PUSBPORT_SCATTER_GATHER_LIST SgList) +{ + PEHCI_HCD_TD PrevTD; + PEHCI_HCD_TD FirstTD; + PEHCI_HCD_TD TD; + ULONG TransferedLen; + + DPRINT_EHCI("EHCI_BulkTransfer: EhciEndpoint - %p, EhciTransfer - %p\n", + EhciEndpoint, + EhciTransfer); + + if (((TransferParameters->TransferBufferLength / + ((EHCI_MAX_QTD_BUFFER_PAGES - 1) * PAGE_SIZE)) + 1) > EhciEndpoint->RemainTDs) + { + DPRINT1("EHCI_BulkTransfer: return MP_STATUS_FAILURE\n"); + return MP_STATUS_FAILURE; + } + + EhciExtension->PendingTransfers++; + EhciEndpoint->PendingTDs++; + + EhciTransfer->TransferOnAsyncList = 1; + + TransferedLen = 0; + PrevTD = NULL; + + if (TransferParameters->TransferBufferLength) + { + while (TransferedLen < TransferParameters->TransferBufferLength) + { + TD = EHCI_AllocTd(EhciExtension, EhciEndpoint); + + if (!TD) + { + RegPacket.UsbPortBugCheck(EhciExtension); + return MP_STATUS_FAILURE; + } + + EhciTransfer->PendingTDs++; + + TD->TdFlags |= EHCI_HCD_TD_FLAG_PROCESSED; + TD->EhciTransfer = EhciTransfer; + + TD->HwTD.Buffer[0] = 0; + TD->HwTD.Buffer[1] = 0; + TD->HwTD.Buffer[2] = 0; + TD->HwTD.Buffer[3] = 0; + TD->HwTD.Buffer[4] = 0; + + TD->NextHcdTD = NULL; + TD->HwTD.NextTD = TERMINATE_POINTER; + TD->HwTD.AlternateNextTD = TERMINATE_POINTER; + + TD->HwTD.Token.AsULONG = 0; + TD->HwTD.Token.ErrorCounter = 3; + + if (EhciTransfer->PendingTDs == 1) + { + FirstTD = TD; + } + else + { + PrevTD->HwTD.NextTD = TD->PhysicalAddress; + PrevTD->NextHcdTD = TD; + } + + TD->HwTD.AlternateNextTD = EhciEndpoint->HcdTailP->PhysicalAddress; + TD->AltNextHcdTD = EhciEndpoint->HcdTailP; + + TD->HwTD.Token.InterruptOnComplete = 1; + + if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) + TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_IN; + else + TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_OUT; + + TD->HwTD.Token.Status = (UCHAR)EHCI_TOKEN_STATUS_ACTIVE; + TD->HwTD.Token.DataToggle = 1; + + TransferedLen = EHCI_MapAsyncTransferToTd(EhciExtension, + EhciEndpoint->EndpointProperties.MaxPacketSize, + TransferedLen, + 0, + EhciTransfer, + TD, + SgList); + + PrevTD = TD; + } + } + else + { + TD = EHCI_AllocTd(EhciExtension, EhciEndpoint); + + if (!TD) + { + RegPacket.UsbPortBugCheck(EhciExtension); + return MP_STATUS_FAILURE; + } + + EhciTransfer->PendingTDs++; + + TD->TdFlags |= EHCI_HCD_TD_FLAG_PROCESSED; + TD->EhciTransfer = EhciTransfer; + + TD->HwTD.Buffer[0] = 0; + TD->HwTD.Buffer[1] = 0; + TD->HwTD.Buffer[2] = 0; + TD->HwTD.Buffer[3] = 0; + TD->HwTD.Buffer[4] = 0; + + TD->HwTD.NextTD = TERMINATE_POINTER; + TD->HwTD.AlternateNextTD = TERMINATE_POINTER; + + TD->HwTD.Token.AsULONG = 0; + TD->HwTD.Token.ErrorCounter = 3; + + TD->NextHcdTD = NULL; + + ASSERT(EhciTransfer->PendingTDs == 1); + + FirstTD = TD; + + TD->HwTD.AlternateNextTD = EhciEndpoint->HcdTailP->PhysicalAddress; + TD->AltNextHcdTD = EhciEndpoint->HcdTailP; + + TD->HwTD.Token.InterruptOnComplete = 1; + + if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) + TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_IN; + else + TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_OUT; + + TD->HwTD.Buffer[0] = TD->PhysicalAddress; + + TD->HwTD.Token.Status = (UCHAR)EHCI_TOKEN_STATUS_ACTIVE; + TD->HwTD.Token.DataToggle = 1; + + TD->LengthThisTD = 0; + } + + TD->HwTD.NextTD = EhciEndpoint->HcdTailP->PhysicalAddress; + TD->NextHcdTD = EhciEndpoint->HcdTailP; + + EHCI_EnableAsyncList(EhciExtension); + EHCI_LinkTransferToQueue(EhciExtension, EhciEndpoint, FirstTD); + + ASSERT(EhciEndpoint->HcdTailP->NextHcdTD == 0); + ASSERT(EhciEndpoint->HcdTailP->AltNextHcdTD == 0); + + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_InterruptTransfer(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint, + IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, + IN PEHCI_TRANSFER EhciTransfer, + IN PUSBPORT_SCATTER_GATHER_LIST SgList) +{ + PEHCI_HCD_TD TD; + PEHCI_HCD_TD FirstTD; + PEHCI_HCD_TD PrevTD = NULL; + ULONG TransferedLen = 0; + + DPRINT_EHCI("EHCI_InterruptTransfer: EhciEndpoint - %p, EhciTransfer - %p\n", + EhciEndpoint, + EhciTransfer); + + if (!EhciEndpoint->RemainTDs) + { + DPRINT1("EHCI_InterruptTransfer: EhciEndpoint - %p\n", EhciEndpoint); + DbgBreakPoint(); + return MP_STATUS_FAILURE; + } + + EhciEndpoint->PendingTDs++; + + if (!TransferParameters->TransferBufferLength) + { + DPRINT1("EHCI_InterruptTransfer: EhciEndpoint - %p\n", EhciEndpoint); + DbgBreakPoint(); + return MP_STATUS_FAILURE; + } + + while (TransferedLen < TransferParameters->TransferBufferLength) + { + TD = EHCI_AllocTd(EhciExtension, EhciEndpoint); + + if (!TD) + { + DPRINT1("EHCI_InterruptTransfer: EhciEndpoint - %p\n", EhciEndpoint); + RegPacket.UsbPortBugCheck(EhciExtension); + return MP_STATUS_FAILURE; + } + + EhciTransfer->PendingTDs++; + + TD->TdFlags |= EHCI_HCD_TD_FLAG_PROCESSED; + TD->EhciTransfer = EhciTransfer; + + TD->HwTD.Buffer[0] = 0; + TD->HwTD.Buffer[1] = 0; + TD->HwTD.Buffer[2] = 0; + TD->HwTD.Buffer[3] = 0; + TD->HwTD.Buffer[4] = 0; + + TD->HwTD.NextTD = TERMINATE_POINTER; + TD->HwTD.AlternateNextTD = TERMINATE_POINTER; + + TD->HwTD.Token.AsULONG = 0; + TD->HwTD.Token.ErrorCounter = 3; + + TD->NextHcdTD = NULL; + + if (EhciTransfer->PendingTDs == 1) + { + FirstTD = TD; + } + else if (PrevTD) + { + PrevTD->HwTD.NextTD = TD->PhysicalAddress; + PrevTD->NextHcdTD = TD; + } + + if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) + TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_IN; + else + TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_OUT; + + TD->HwTD.Token.Status = (UCHAR)EHCI_TOKEN_STATUS_ACTIVE; + TD->HwTD.Token.DataToggle = 1; + + TransferedLen = EHCI_MapAsyncTransferToTd(EhciExtension, + EhciEndpoint->EndpointProperties.TotalMaxPacketSize, + TransferedLen, + NULL, + EhciTransfer, + TD, + SgList); + + PrevTD = TD; + } + + TD->HwTD.Token.InterruptOnComplete = 1; + + DPRINT_EHCI("EHCI_InterruptTransfer: PendingTDs - %x, TD->PhysicalAddress - %p, FirstTD - %p\n", + EhciTransfer->PendingTDs, + TD->PhysicalAddress, + FirstTD); + + TD->HwTD.NextTD = EhciEndpoint->HcdTailP->PhysicalAddress; + TD->NextHcdTD = EhciEndpoint->HcdTailP; + + EHCI_LinkTransferToQueue(EhciExtension, EhciEndpoint, FirstTD); + + ASSERT(EhciEndpoint->HcdTailP->NextHcdTD == NULL); + ASSERT(EhciEndpoint->HcdTailP->AltNextHcdTD == NULL); + + EHCI_EnablePeriodicList(EhciExtension); + + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_SubmitTransfer(IN PVOID ehciExtension, + IN PVOID ehciEndpoint, + IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, + IN PVOID ehciTransfer, + IN PUSBPORT_SCATTER_GATHER_LIST SgList) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PEHCI_ENDPOINT EhciEndpoint = ehciEndpoint; + PEHCI_TRANSFER EhciTransfer = ehciTransfer; + MPSTATUS MPStatus; + + DPRINT_EHCI("EHCI_SubmitTransfer: EhciEndpoint - %p, EhciTransfer - %p\n", + EhciEndpoint, + EhciTransfer); + + RtlZeroMemory(EhciTransfer, sizeof(EHCI_TRANSFER)); + + EhciTransfer->TransferParameters = TransferParameters; + EhciTransfer->USBDStatus = USBD_STATUS_SUCCESS; + EhciTransfer->EhciEndpoint = EhciEndpoint; + + switch (EhciEndpoint->EndpointProperties.TransferType) + { + case USBPORT_TRANSFER_TYPE_CONTROL: + MPStatus = EHCI_ControlTransfer(EhciExtension, + EhciEndpoint, + TransferParameters, + EhciTransfer, + SgList); + break; + + case USBPORT_TRANSFER_TYPE_BULK: + MPStatus = EHCI_BulkTransfer(EhciExtension, + EhciEndpoint, + TransferParameters, + EhciTransfer, + SgList); + break; + + case USBPORT_TRANSFER_TYPE_INTERRUPT: + MPStatus = EHCI_InterruptTransfer(EhciExtension, + EhciEndpoint, + TransferParameters, + EhciTransfer, + SgList); + break; + + default: + DbgBreakPoint(); + MPStatus = MP_STATUS_NOT_SUPPORTED; + break; + } + + return MPStatus; +} + +MPSTATUS +NTAPI +EHCI_SubmitIsoTransfer(IN PVOID ehciExtension, + IN PVOID ehciEndpoint, + IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, + IN PVOID ehciTransfer, + IN PVOID isoParameters) +{ + DPRINT1("EHCI_SubmitIsoTransfer: UNIMPLEMENTED. FIXME\n"); + return MP_STATUS_SUCCESS; +} + +VOID +NTAPI +EHCI_AbortIsoTransfer(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint, + IN PEHCI_TRANSFER EhciTransfer) +{ + DPRINT1("EHCI_AbortIsoTransfer: UNIMPLEMENTED. FIXME\n"); +} + +VOID +NTAPI +EHCI_AbortAsyncTransfer(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint, + IN PEHCI_TRANSFER EhciTransfer) +{ + PEHCI_HCD_QH QH; + PEHCI_HCD_TD TD; + ULONG TransferLength; + PEHCI_HCD_TD CurrentTD; + PEHCI_TRANSFER CurrentTransfer; + ULONG FirstTdPA; + PEHCI_HCD_TD LastTD; + PEHCI_HCD_TD PrevTD; + ULONG NextTD; + + DPRINT("EHCI_AbortAsyncTransfer: EhciEndpoint - %p, EhciTransfer - %p\n", + EhciEndpoint, + EhciTransfer); + + QH = EhciEndpoint->QH; + TD = EhciEndpoint->HcdHeadP; + + ASSERT(EhciEndpoint->PendingTDs); + EhciEndpoint->PendingTDs--; + + if (TD->EhciTransfer == EhciTransfer) + { + TransferLength = 0; + + while (TD != EhciEndpoint->HcdTailP && + TD->EhciTransfer == EhciTransfer) + { + TransferLength += TD->LengthThisTD - TD->HwTD.Token.TransferBytes; + + TD->HwTD.NextTD = 0; + TD->HwTD.AlternateNextTD = 0; + + TD->TdFlags = 0; + TD->EhciTransfer = NULL; + + EhciEndpoint->RemainTDs++; + + TD = TD->NextHcdTD; + } + + if (TransferLength) + EhciTransfer->TransferLen += TransferLength; + + QH->sqh.HwQH.CurrentTD = EhciEndpoint->DmaBufferPA; + QH->sqh.HwQH.NextTD = TD->PhysicalAddress; + QH->sqh.HwQH.AlternateNextTD = TD->HwTD.AlternateNextTD; + + QH->sqh.HwQH.Token.TransferBytes = 0; + QH->sqh.HwQH.Token.Status = (UCHAR)~(EHCI_TOKEN_STATUS_ACTIVE | + EHCI_TOKEN_STATUS_HALTED); + + EhciEndpoint->HcdHeadP = TD; + } + else + { + DPRINT("EHCI_AbortAsyncTransfer: TD->EhciTransfer - %p\n", TD->EhciTransfer); + + CurrentTD = RegPacket.UsbPortGetMappedVirtualAddress(QH->sqh.HwQH.CurrentTD, + EhciExtension, + EhciEndpoint); + + CurrentTransfer = CurrentTD->EhciTransfer; + TD = EhciEndpoint->HcdHeadP; + + while (TD && TD->EhciTransfer != EhciTransfer) + { + PrevTD = TD; + TD = TD->NextHcdTD; + } + + FirstTdPA = TD->PhysicalAddress; + + while (TD && TD->EhciTransfer == EhciTransfer) + { + TD->HwTD.NextTD = 0; + TD->HwTD.AlternateNextTD = 0; + + TD->TdFlags = 0; + TD->EhciTransfer = NULL; + + EhciEndpoint->RemainTDs++; + + TD = TD->NextHcdTD; + } + + LastTD = TD; + NextTD = LastTD->PhysicalAddress + FIELD_OFFSET(EHCI_HCD_TD, HwTD.NextTD); + + PrevTD->HwTD.NextTD = LastTD->PhysicalAddress; + PrevTD->HwTD.AlternateNextTD = LastTD->PhysicalAddress; + + PrevTD->NextHcdTD = LastTD; + PrevTD->AltNextHcdTD = LastTD; + + if (CurrentTransfer == EhciTransfer) + { + QH->sqh.HwQH.CurrentTD = EhciEndpoint->DmaBufferPA; + + QH->sqh.HwQH.Token.Status = (UCHAR)~EHCI_TOKEN_STATUS_ACTIVE; + QH->sqh.HwQH.Token.TransferBytes = 0; + + QH->sqh.HwQH.NextTD = NextTD; + QH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; + + return; + } + + if (PrevTD->EhciTransfer == CurrentTransfer) + { + if (QH->sqh.HwQH.NextTD == FirstTdPA) + QH->sqh.HwQH.NextTD = NextTD; + + if (QH->sqh.HwQH.AlternateNextTD == FirstTdPA) + QH->sqh.HwQH.AlternateNextTD = NextTD; + + for (TD = EhciEndpoint->HcdHeadP; + TD; + TD = TD->NextHcdTD) + { + if (TD->EhciTransfer == CurrentTransfer) + { + TD->HwTD.AlternateNextTD = NextTD; + TD->AltNextHcdTD = LastTD; + } + } + } + } +} + +VOID +NTAPI +EHCI_AbortTransfer(IN PVOID ehciExtension, + IN PVOID ehciEndpoint, + IN PVOID ehciTransfer, + IN PULONG CompletedLength) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PEHCI_ENDPOINT EhciEndpoint = ehciEndpoint; + PEHCI_TRANSFER EhciTransfer = ehciTransfer; + ULONG TransferType; + + DPRINT("EHCI_AbortTransfer: EhciTransfer - %p, CompletedLength - %x\n", + EhciTransfer, + CompletedLength); + + TransferType = EhciEndpoint->EndpointProperties.TransferType; + + if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) + EHCI_AbortIsoTransfer(EhciExtension, EhciEndpoint, EhciTransfer); + else + EHCI_AbortAsyncTransfer(EhciExtension, EhciEndpoint, EhciTransfer); +} + +ULONG +NTAPI +EHCI_GetEndpointState(IN PVOID ehciExtension, + IN PVOID ehciEndpoint) +{ + DPRINT1("EHCI_GetEndpointState: UNIMPLEMENTED. FIXME\n"); + return 0; +} + +VOID +NTAPI +EHCI_RemoveQhFromPeriodicList(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint) +{ + PEHCI_HCD_QH QH; + PEHCI_HCD_QH NextHead; + ULONG NextQhPA; + PEHCI_HCD_QH PrevHead; + + QH = EhciEndpoint->QH; + + if (!(QH->sqh.QhFlags & EHCI_QH_FLAG_IN_SCHEDULE)) + return; + + DPRINT("EHCI_RemoveQhFromPeriodicList: EhciEndpoint - %p, QH - %X, EhciEndpoint->StaticQH - %p\n", + EhciEndpoint, + QH, + EhciEndpoint->StaticQH); + + NextHead = QH->sqh.NextHead; + PrevHead = QH->sqh.PrevHead; + + PrevHead->sqh.NextHead = NextHead; + + if (NextHead) + { + if (!(NextHead->sqh.QhFlags & EHCI_QH_FLAG_STATIC)) + NextHead->sqh.PrevHead = PrevHead; + + NextQhPA = NextHead->sqh.PhysicalAddress; + NextQhPA &= LINK_POINTER_MASK + TERMINATE_POINTER; + NextQhPA |= (EHCI_LINK_TYPE_QH << 1); + + PrevHead->sqh.HwQH.HorizontalLink.AsULONG = NextQhPA; + } + else + { + PrevHead->sqh.HwQH.HorizontalLink.Terminate = 1; + } + + QH->sqh.QhFlags &= ~EHCI_QH_FLAG_IN_SCHEDULE; + + QH->sqh.NextHead = NULL; + QH->sqh.PrevHead = NULL; +} + +VOID +NTAPI +EHCI_RemoveQhFromAsyncList(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_HCD_QH QH) +{ + PEHCI_HCD_QH NextHead; + ULONG NextHeadPA; + PEHCI_HCD_QH PrevHead; + PEHCI_STATIC_QH AsyncHead; + ULONG AsyncHeadPA; + + DPRINT("EHCI_RemoveQhFromAsyncList: QH - %p\n", QH); + + if (QH->sqh.QhFlags & EHCI_QH_FLAG_IN_SCHEDULE) + { + NextHead = QH->sqh.NextHead; + PrevHead = QH->sqh.PrevHead; + + AsyncHead = EhciExtension->AsyncHead; + + AsyncHeadPA = AsyncHead->PhysicalAddress; + AsyncHeadPA &= LINK_POINTER_MASK + TERMINATE_POINTER; + AsyncHeadPA |= (EHCI_LINK_TYPE_QH << 1); + + NextHeadPA = NextHead->sqh.PhysicalAddress; + NextHeadPA &= LINK_POINTER_MASK + TERMINATE_POINTER; + NextHeadPA |= (EHCI_LINK_TYPE_QH << 1); + + PrevHead->sqh.HwQH.HorizontalLink.AsULONG = NextHeadPA; + + PrevHead->sqh.NextHead = NextHead; + NextHead->sqh.PrevHead = PrevHead; + + EHCI_FlushAsyncCache(EhciExtension); + + if (READ_REGISTER_ULONG(&EhciExtension->OperationalRegs->AsyncListBase) == + QH->sqh.PhysicalAddress) + { + WRITE_REGISTER_ULONG(&EhciExtension->OperationalRegs->AsyncListBase, + AsyncHeadPA); + } + + QH->sqh.QhFlags &= ~EHCI_QH_FLAG_IN_SCHEDULE; + } +} + +VOID +NTAPI +EHCI_InsertQhInPeriodicList(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint) +{ + PEHCI_STATIC_QH StaticQH; + PEHCI_HCD_QH QH; + ULONG QhPA; + PEHCI_HCD_QH NextHead; + PEHCI_HCD_QH PrevHead; + + QH = EhciEndpoint->QH; + StaticQH = EhciEndpoint->StaticQH; + + ASSERT((QH->sqh.QhFlags & EHCI_QH_FLAG_IN_SCHEDULE) == 0); + ASSERT(StaticQH->QhFlags & EHCI_QH_FLAG_STATIC); + + NextHead = StaticQH->NextHead; + + QH->sqh.Period = EhciEndpoint->EndpointProperties.Period; + QH->sqh.Ordinal = EhciEndpoint->EndpointProperties.Reserved6; + + DPRINT("EHCI_InsertQhInPeriodicList: EhciEndpoint - %p, QH - %X, EhciEndpoint->StaticQH - %p\n", + EhciEndpoint, + QH, + EhciEndpoint->StaticQH); + + PrevHead = (PEHCI_HCD_QH)StaticQH; + + if ((StaticQH->QhFlags & EHCI_QH_FLAG_STATIC) && + (!NextHead || (NextHead->sqh.QhFlags & EHCI_QH_FLAG_STATIC))) + { + DPRINT("EHCI_InsertQhInPeriodicList: StaticQH - %p, StaticQH->NextHead - %p\n", + StaticQH, + StaticQH->NextHead); + } + else + { + while (NextHead && + !(NextHead->sqh.QhFlags & EHCI_QH_FLAG_STATIC) && + QH->sqh.Ordinal > NextHead->sqh.Ordinal) + { + PrevHead = NextHead; + NextHead = NextHead->sqh.NextHead; + } + } + + QH->sqh.NextHead = NextHead; + QH->sqh.PrevHead = PrevHead; + + if (NextHead && !(NextHead->sqh.QhFlags & EHCI_QH_FLAG_STATIC)) + NextHead->sqh.PrevHead = QH; + + QH->sqh.QhFlags |= EHCI_QH_FLAG_IN_SCHEDULE; + QH->sqh.HwQH.HorizontalLink = PrevHead->sqh.HwQH.HorizontalLink; + + PrevHead->sqh.NextHead = QH; + + QhPA = QH->sqh.PhysicalAddress; + QhPA &= LINK_POINTER_MASK + TERMINATE_POINTER; + QhPA |= (EHCI_LINK_TYPE_QH << 1); + + PrevHead->sqh.HwQH.HorizontalLink.AsULONG = QhPA; +} + +VOID +NTAPI +EHCI_InsertQhInAsyncList(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_HCD_QH QH) +{ + PEHCI_STATIC_QH AsyncHead; + ULONG QhPA; + PEHCI_HCD_QH NextHead; + + DPRINT("EHCI_InsertQhInAsyncList: QH - %p\n", QH); + + ASSERT((QH->sqh.QhFlags & EHCI_QH_FLAG_IN_SCHEDULE) == 0); + ASSERT((QH->sqh.QhFlags & EHCI_QH_FLAG_NUKED) == 0); + + AsyncHead = EhciExtension->AsyncHead; + NextHead = AsyncHead->NextHead; + + QH->sqh.HwQH.HorizontalLink = AsyncHead->HwQH.HorizontalLink; + QH->sqh.QhFlags |= EHCI_QH_FLAG_IN_SCHEDULE; + QH->sqh.NextHead = NextHead; + QH->sqh.PrevHead = (PEHCI_HCD_QH)AsyncHead; + + NextHead->sqh.PrevHead = QH; + + QhPA = QH->sqh.PhysicalAddress; + QhPA &= LINK_POINTER_MASK + TERMINATE_POINTER; + QhPA |= (EHCI_LINK_TYPE_QH << 1); + + AsyncHead->HwQH.HorizontalLink.AsULONG = QhPA; + + AsyncHead->NextHead = QH; +} + +VOID +NTAPI +EHCI_SetIsoEndpointState(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint, + IN ULONG EndpointState) +{ + DPRINT1("EHCI_SetIsoEndpointState: UNIMPLEMENTED. FIXME\n"); +} + +VOID +NTAPI +EHCI_SetAsyncEndpointState(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint, + IN ULONG EndpointState) +{ + PEHCI_HCD_QH QH; + ULONG TransferType; + + DPRINT("EHCI_SetAsyncEndpointState: EhciEndpoint - %p, EndpointState - %x\n", + EhciEndpoint, + EndpointState); + + QH = EhciEndpoint->QH; + + TransferType = EhciEndpoint->EndpointProperties.TransferType; + + switch (EndpointState) + { + case USBPORT_ENDPOINT_PAUSED: + if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) + EHCI_RemoveQhFromPeriodicList(EhciExtension, EhciEndpoint); + else + EHCI_RemoveQhFromAsyncList(EhciExtension, EhciEndpoint->QH); + + break; + + case USBPORT_ENDPOINT_ACTIVE: + if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) + EHCI_InsertQhInPeriodicList(EhciExtension, EhciEndpoint); + else + EHCI_InsertQhInAsyncList(EhciExtension, EhciEndpoint->QH); + + break; + + case USBPORT_ENDPOINT_REMOVE: + QH->sqh.QhFlags |= EHCI_QH_FLAG_CLOSED; + + if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) + EHCI_RemoveQhFromPeriodicList(EhciExtension, EhciEndpoint); + else + EHCI_RemoveQhFromAsyncList(EhciExtension, EhciEndpoint->QH); + + break; + + default: + DbgBreakPoint(); + break; + } + + EhciEndpoint->EndpointState = EndpointState; +} + +VOID +NTAPI +EHCI_SetEndpointState(IN PVOID ehciExtension, + IN PVOID ehciEndpoint, + IN ULONG EndpointState) +{ + PEHCI_ENDPOINT EhciEndpoint; + ULONG TransferType; + + DPRINT("EHCI_SetEndpointState: ... \n"); + + EhciEndpoint = ehciEndpoint; + TransferType = EhciEndpoint->EndpointProperties.TransferType; + + if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL || + TransferType == USBPORT_TRANSFER_TYPE_BULK || + TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) + { + EHCI_SetAsyncEndpointState((PEHCI_EXTENSION)ehciExtension, + EhciEndpoint, + EndpointState); + } + else if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) + { + EHCI_SetIsoEndpointState((PEHCI_EXTENSION)ehciExtension, + EhciEndpoint, + EndpointState); + } + else + { + RegPacket.UsbPortBugCheck(ehciExtension); + } +} + +VOID +NTAPI +EHCI_InterruptNextSOF(IN PVOID ehciExtension) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + + DPRINT_EHCI("EHCI_InterruptNextSOF: ... \n"); + + RegPacket.UsbPortInvalidateController(EhciExtension, + USBPORT_INVALIDATE_CONTROLLER_SOFT_INTERRUPT); +} + +USBD_STATUS +NTAPI +EHCI_GetErrorFromTD(IN PEHCI_HCD_TD TD) +{ + EHCI_TD_TOKEN Token; + + DPRINT_EHCI("EHCI_GetErrorFromTD: ... \n"); + + ASSERT(TD->HwTD.Token.Status & EHCI_TOKEN_STATUS_HALTED); + + Token = TD->HwTD.Token; + + if (Token.Status & EHCI_TOKEN_STATUS_TRANSACTION_ERROR) + { + DPRINT("EHCI_GetErrorFromTD: TD - %p, TRANSACTION_ERROR\n", TD); + return USBD_STATUS_XACT_ERROR; + } + + if (Token.Status & EHCI_TOKEN_STATUS_BABBLE_DETECTED) + { + DPRINT("EHCI_GetErrorFromTD: TD - %p, BABBLE_DETECTED\n", TD); + return USBD_STATUS_BABBLE_DETECTED; + } + + if (Token.Status & EHCI_TOKEN_STATUS_DATA_BUFFER_ERROR) + { + DPRINT("EHCI_GetErrorFromTD: TD - %p, DATA_BUFFER_ERROR\n", TD); + return USBD_STATUS_DATA_BUFFER_ERROR; + } + + if (Token.Status & EHCI_TOKEN_STATUS_MISSED_MICROFRAME) + { + DPRINT("EHCI_GetErrorFromTD: TD - %p, MISSED_MICROFRAME\n", TD); + return USBD_STATUS_XACT_ERROR; + } + + DPRINT("EHCI_GetErrorFromTD: TD - %p, STALL_PID\n", TD); + return USBD_STATUS_STALL_PID; +} + +VOID +NTAPI +EHCI_ProcessDoneAsyncTd(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_HCD_TD TD) +{ + PEHCI_TRANSFER EhciTransfer; + PUSBPORT_TRANSFER_PARAMETERS TransferParameters; + ULONG TransferType; + PEHCI_ENDPOINT EhciEndpoint; + ULONG LengthTransfered; + USBD_STATUS USBDStatus; + PEHCI_HW_REGISTERS OperationalRegs; + EHCI_USB_COMMAND Command; + + DPRINT_EHCI("EHCI_ProcessDoneAsyncTd: TD - %p\n", TD); + + EhciTransfer = TD->EhciTransfer; + + TransferParameters = EhciTransfer->TransferParameters; + EhciTransfer->PendingTDs--; + + EhciEndpoint = EhciTransfer->EhciEndpoint; + + if (!(TD->TdFlags & EHCI_HCD_TD_FLAG_ACTIVE)) + { + + if (TD->HwTD.Token.Status & EHCI_TOKEN_STATUS_HALTED) + USBDStatus = EHCI_GetErrorFromTD(TD); + else + USBDStatus = USBD_STATUS_SUCCESS; + + LengthTransfered = TD->LengthThisTD - TD->HwTD.Token.TransferBytes; + + if (TD->HwTD.Token.PIDCode != EHCI_TD_TOKEN_PID_SETUP) + EhciTransfer->TransferLen += LengthTransfered; + + if (USBDStatus != USBD_STATUS_SUCCESS) + EhciTransfer->USBDStatus = USBDStatus; + } + + TD->HwTD.NextTD = 0; + TD->HwTD.AlternateNextTD = 0; + + TD->TdFlags = 0; + TD->EhciTransfer = NULL; + + EhciEndpoint->RemainTDs++; + + if (EhciTransfer->PendingTDs == 0) + { + EhciEndpoint->PendingTDs--; + + TransferType = EhciEndpoint->EndpointProperties.TransferType; + + if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL || + TransferType == USBPORT_TRANSFER_TYPE_BULK) + { + EhciExtension->PendingTransfers--; + + if (EhciExtension->PendingTransfers == 0) + { + OperationalRegs = EhciExtension->OperationalRegs; + Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); + + if (!Command.InterruptAdvanceDoorbell && + (EhciExtension->Flags & EHCI_FLAGS_IDLE_SUPPORT)) + { + EHCI_DisableAsyncList(EhciExtension); + } + } + } + + RegPacket.UsbPortCompleteTransfer(EhciExtension, + EhciEndpoint, + TransferParameters, + EhciTransfer->USBDStatus, + EhciTransfer->TransferLen); + } +} + +VOID +NTAPI +EHCI_PollActiveAsyncEndpoint(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint) +{ + PEHCI_HCD_QH QH; + PEHCI_HCD_TD TD; + PEHCI_HCD_TD CurrentTD; + ULONG CurrentTDPhys; + BOOLEAN IsScheduled; + + DPRINT_EHCI("EHCI_PollActiveAsyncEndpoint: ... \n"); + + QH = EhciEndpoint->QH; + + CurrentTDPhys = QH->sqh.HwQH.CurrentTD & LINK_POINTER_MASK; + ASSERT(CurrentTDPhys); + + CurrentTD = RegPacket.UsbPortGetMappedVirtualAddress(CurrentTDPhys, + EhciExtension, + EhciEndpoint); + + if (CurrentTD == EhciEndpoint->DmaBufferVA) + return; + + IsScheduled = QH->sqh.QhFlags & EHCI_QH_FLAG_IN_SCHEDULE; + + if (!EHCI_HardwarePresent(EhciExtension, 0)) + IsScheduled = 0; + + TD = EhciEndpoint->HcdHeadP; + + if (TD == CurrentTD) + { + if (TD != EhciEndpoint->HcdTailP && + !(TD->HwTD.Token.Status & EHCI_TOKEN_STATUS_ACTIVE)) + { + if (TD->NextHcdTD && TD->HwTD.NextTD != TD->NextHcdTD->PhysicalAddress) + TD->HwTD.NextTD = TD->NextHcdTD->PhysicalAddress; + + if (TD->AltNextHcdTD && + TD->HwTD.AlternateNextTD != TD->AltNextHcdTD->PhysicalAddress) + { + TD->HwTD.AlternateNextTD = TD->AltNextHcdTD->PhysicalAddress; + } + + if (QH->sqh.HwQH.CurrentTD == TD->PhysicalAddress && + !(TD->HwTD.Token.Status & EHCI_TOKEN_STATUS_ACTIVE) && + (QH->sqh.HwQH.NextTD != TD->HwTD.NextTD || + QH->sqh.HwQH.AlternateNextTD != TD->HwTD.AlternateNextTD)) + { + QH->sqh.HwQH.NextTD = TD->HwTD.NextTD; + QH->sqh.HwQH.AlternateNextTD = TD->HwTD.AlternateNextTD; + } + + EHCI_InterruptNextSOF(EhciExtension); + } + } + else + { + while (TD != CurrentTD) + { + ASSERT((TD->TdFlags & EHCI_HCD_TD_FLAG_DUMMY) == 0); + + TD->TdFlags |= EHCI_HCD_TD_FLAG_DONE; + + if (TD->HwTD.Token.Status & EHCI_TOKEN_STATUS_ACTIVE) + TD->TdFlags |= EHCI_HCD_TD_FLAG_ACTIVE; + + InsertTailList(&EhciEndpoint->ListTDs, &TD->DoneLink); + TD = TD->NextHcdTD; + } + } + + if (CurrentTD->HwTD.Token.Status & EHCI_TOKEN_STATUS_ACTIVE) + { + ASSERT(TD != NULL); + EhciEndpoint->HcdHeadP = TD; + return; + } + + if ((CurrentTD->NextHcdTD != EhciEndpoint->HcdTailP) && + (CurrentTD->AltNextHcdTD != EhciEndpoint->HcdTailP || + CurrentTD->HwTD.Token.TransferBytes == 0)) + { + ASSERT(TD != NULL); + EhciEndpoint->HcdHeadP = TD; + return; + } + + if (IsScheduled) + { + EHCI_LockQH(EhciExtension, + QH, + EhciEndpoint->EndpointProperties.TransferType); + } + + QH->sqh.HwQH.CurrentTD = EhciEndpoint->DmaBufferPA; + + CurrentTD->TdFlags |= EHCI_HCD_TD_FLAG_DONE; + InsertTailList(&EhciEndpoint->ListTDs, &CurrentTD->DoneLink); + + if (CurrentTD->HwTD.Token.TransferBytes && + CurrentTD->AltNextHcdTD == EhciEndpoint->HcdTailP) + { + TD = CurrentTD->NextHcdTD; + + while (TD != EhciEndpoint->HcdTailP) + { + TD->TdFlags |= EHCI_HCD_TD_FLAG_ACTIVE; + InsertTailList(&EhciEndpoint->ListTDs, &TD->DoneLink); + TD = TD->NextHcdTD; + } + } + + QH->sqh.HwQH.CurrentTD = EhciEndpoint->HcdTailP->PhysicalAddress; + QH->sqh.HwQH.NextTD = TERMINATE_POINTER; + QH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; + QH->sqh.HwQH.Token.TransferBytes = 0; + + EhciEndpoint->HcdHeadP = EhciEndpoint->HcdTailP; + + if (IsScheduled) + EHCI_UnlockQH(EhciExtension, QH); +} + +VOID +NTAPI +EHCI_PollHaltedAsyncEndpoint(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint) +{ + PEHCI_HCD_QH QH; + PEHCI_HCD_TD CurrentTD; + ULONG CurrentTdPA; + PEHCI_HCD_TD TD; + PEHCI_TRANSFER Transfer; + BOOLEAN IsScheduled; + + DPRINT("EHCI_PollHaltedAsyncEndpoint: EhciEndpoint - %p\n", EhciEndpoint); + + QH = EhciEndpoint->QH; + EHCI_DumpHwQH(QH); + + CurrentTdPA = QH->sqh.HwQH.CurrentTD & LINK_POINTER_MASK; + ASSERT(CurrentTdPA); + + IsScheduled = QH->sqh.QhFlags & EHCI_QH_FLAG_IN_SCHEDULE; + + if (!EHCI_HardwarePresent(EhciExtension, 0)) + IsScheduled = 0; + + CurrentTD = RegPacket.UsbPortGetMappedVirtualAddress(CurrentTdPA, + EhciExtension, + EhciEndpoint); + + DPRINT("EHCI_PollHaltedAsyncEndpoint: CurrentTD - %p\n", CurrentTD); + + if (CurrentTD == EhciEndpoint->DmaBufferVA) + return; + + ASSERT(EhciEndpoint->HcdTailP != CurrentTD); + + if (IsScheduled) + { + EHCI_LockQH(EhciExtension, + QH, + EhciEndpoint->EndpointProperties.TransferType); + } + + TD = EhciEndpoint->HcdHeadP; + + while (TD != CurrentTD) + { + DPRINT("EHCI_PollHaltedAsyncEndpoint: TD - %p\n", TD); + + ASSERT((TD->TdFlags & EHCI_HCD_TD_FLAG_DUMMY) == 0); + + if (TD->HwTD.Token.Status & EHCI_TOKEN_STATUS_ACTIVE) + TD->TdFlags |= EHCI_HCD_TD_FLAG_ACTIVE; + + TD->TdFlags |= EHCI_HCD_TD_FLAG_DONE; + + InsertTailList(&EhciEndpoint->ListTDs, &TD->DoneLink); + + TD = TD->NextHcdTD; + } + + TD = CurrentTD; + + Transfer = CurrentTD->EhciTransfer; + + do + { + DPRINT("EHCI_PollHaltedAsyncEndpoint: TD - %p\n", TD); + + if (TD->HwTD.Token.Status & EHCI_TOKEN_STATUS_ACTIVE) + TD->TdFlags |= EHCI_HCD_TD_FLAG_ACTIVE; + + TD->TdFlags |= EHCI_HCD_TD_FLAG_DONE; + + InsertTailList(&EhciEndpoint->ListTDs, &TD->DoneLink); + + TD = TD->NextHcdTD; + } + while (TD->EhciTransfer == Transfer); + + EhciEndpoint->HcdHeadP = TD; + + QH->sqh.HwQH.CurrentTD = EhciEndpoint->DmaBufferPA; + QH->sqh.HwQH.NextTD = TD->PhysicalAddress; + QH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; + QH->sqh.HwQH.Token.TransferBytes = 0; + + if (IsScheduled) + EHCI_UnlockQH(EhciExtension, QH); + + if (EhciEndpoint->EndpointStatus & USBPORT_ENDPOINT_CONTROL) + { + EhciEndpoint->EndpointStatus &= ~USBPORT_ENDPOINT_HALT; + QH->sqh.HwQH.Token.ErrorCounter = 0; + QH->sqh.HwQH.Token.Status &= (UCHAR)~(EHCI_TOKEN_STATUS_ACTIVE | + EHCI_TOKEN_STATUS_HALTED); + + } +} + +VOID +NTAPI +EHCI_PollAsyncEndpoint(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint) +{ + PEHCI_HCD_QH QH; + PLIST_ENTRY DoneList; + PEHCI_HCD_TD TD; + + //DPRINT_EHCI("EHCI_PollAsyncEndpoint: EhciEndpoint - %p\n", EhciEndpoint); + + if (!EhciEndpoint->PendingTDs) + return; + + QH = EhciEndpoint->QH; + + if (QH->sqh.QhFlags & EHCI_QH_FLAG_CLOSED) + return; + + if (QH->sqh.HwQH.Token.Status & EHCI_TOKEN_STATUS_ACTIVE || + !(QH->sqh.HwQH.Token.Status & EHCI_TOKEN_STATUS_HALTED)) + { + EHCI_PollActiveAsyncEndpoint(EhciExtension, EhciEndpoint); + } + else + { + EhciEndpoint->EndpointStatus |= USBPORT_ENDPOINT_HALT; + EHCI_PollHaltedAsyncEndpoint(EhciExtension, EhciEndpoint); + } + + DoneList = &EhciEndpoint->ListTDs; + + while (!IsListEmpty(DoneList)) + { + TD = CONTAINING_RECORD(DoneList->Flink, + EHCI_HCD_TD, + DoneLink); + + RemoveHeadList(DoneList); + + ASSERT((TD->TdFlags & (EHCI_HCD_TD_FLAG_PROCESSED | + EHCI_HCD_TD_FLAG_DONE))); + + EHCI_ProcessDoneAsyncTd(EhciExtension, TD); + } +} + +VOID +NTAPI +EHCI_PollIsoEndpoint(IN PEHCI_EXTENSION EhciExtension, + IN PEHCI_ENDPOINT EhciEndpoint) +{ + DPRINT1("EHCI_PollIsoEndpoint: UNIMPLEMENTED. FIXME\n"); +} + +VOID +NTAPI +EHCI_PollEndpoint(IN PVOID ehciExtension, + IN PVOID ehciEndpoint) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PEHCI_ENDPOINT EhciEndpoint = ehciEndpoint; + ULONG TransferType; + + //DPRINT_EHCI("EHCI_PollEndpoint: EhciEndpoint - %p\n", EhciEndpoint); + + TransferType = EhciEndpoint->EndpointProperties.TransferType; + + if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) + EHCI_PollIsoEndpoint(EhciExtension, EhciEndpoint); + else + EHCI_PollAsyncEndpoint(EhciExtension, EhciEndpoint); +} + +VOID +NTAPI +EHCI_CheckController(IN PVOID ehciExtension) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + + //DPRINT_EHCI("EHCI_CheckController: ... \n"); + + if (EhciExtension->IsStarted) + EHCI_HardwarePresent(EhciExtension, TRUE); +} + +ULONG +NTAPI +EHCI_Get32BitFrameNumber(IN PVOID ehciExtension) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + ULONG FrameIdx; + ULONG FrameIndex; + ULONG FrameNumber; + + //DPRINT_EHCI("EHCI_Get32BitFrameNumber: EhciExtension - %p\n", EhciExtension); + + FrameIdx = EhciExtension->FrameIndex; + FrameIndex = READ_REGISTER_ULONG(&EhciExtension->OperationalRegs->FrameIndex); + + FrameNumber = (USHORT)FrameIdx ^ ((FrameIndex / EHCI_MICROFRAMES) & EHCI_FRINDEX_FRAME_MASK); + FrameNumber &= EHCI_FRAME_LIST_MAX_ENTRIES; + FrameNumber += FrameIndex | ((FrameIndex / EHCI_MICROFRAMES) & EHCI_FRINDEX_INDEX_MASK); + + return FrameNumber; +} + +VOID +NTAPI +EHCI_EnableInterrupts(IN PVOID ehciExtension) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + + DPRINT("EHCI_EnableInterrupts: EhciExtension->InterruptMask - %x\n", + EhciExtension->InterruptMask.AsULONG); + + WRITE_REGISTER_ULONG(&EhciExtension->OperationalRegs->HcInterruptEnable.AsULONG, + EhciExtension->InterruptMask.AsULONG); +} + +VOID +NTAPI +EHCI_DisableInterrupts(IN PVOID ehciExtension) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + + DPRINT("EHCI_DisableInterrupts: ... \n"); + + WRITE_REGISTER_ULONG(&EhciExtension->OperationalRegs->HcInterruptEnable.AsULONG, + 0); +} + +VOID +NTAPI +EHCI_PollController(IN PVOID ehciExtension) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PEHCI_HW_REGISTERS OperationalRegs; + ULONG Port; + EHCI_PORT_STATUS_CONTROL PortSC; + + DPRINT_EHCI("EHCI_PollController: ... \n"); + + OperationalRegs = EhciExtension->OperationalRegs; + + if (!(EhciExtension->Flags & EHCI_FLAGS_CONTROLLER_SUSPEND)) + { + RegPacket.UsbPortInvalidateRootHub(EhciExtension); + return; + } + + if (EhciExtension->NumberOfPorts) + { + for (Port = 0; Port < EhciExtension->NumberOfPorts; Port++) + { + PortSC.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->PortControl[Port].AsULONG); + + if (PortSC.ConnectStatusChange) + RegPacket.UsbPortInvalidateRootHub(EhciExtension); + } + } +} + +VOID +NTAPI +EHCI_SetEndpointDataToggle(IN PVOID ehciExtension, + IN PVOID ehciEndpoint, + IN ULONG DataToggle) +{ + PEHCI_ENDPOINT EhciEndpoint; + ULONG TransferType; + + EhciEndpoint = ehciEndpoint; + + DPRINT("EHCI_SetEndpointDataToggle: EhciEndpoint - %p, DataToggle - %x\n", + EhciEndpoint, + DataToggle); + + TransferType = EhciEndpoint->EndpointProperties.TransferType; + + if (TransferType == USBPORT_TRANSFER_TYPE_BULK || + TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) + { + EhciEndpoint->QH->sqh.HwQH.Token.DataToggle = DataToggle; + } +} + +ULONG +NTAPI +EHCI_GetEndpointStatus(IN PVOID ehciExtension, + IN PVOID ehciEndpoint) +{ + PEHCI_ENDPOINT EhciEndpoint; + ULONG TransferType; + ULONG EndpointStatus = USBPORT_ENDPOINT_RUN; + + EhciEndpoint = ehciEndpoint; + + DPRINT("EHCI_GetEndpointStatus: EhciEndpoint - %p\n", EhciEndpoint); + + TransferType = EhciEndpoint->EndpointProperties.TransferType; + + if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) + return EndpointStatus; + + if (EhciEndpoint->EndpointStatus & USBPORT_ENDPOINT_HALT) + EndpointStatus = USBPORT_ENDPOINT_HALT; + + return EndpointStatus; +} + +VOID +NTAPI +EHCI_SetEndpointStatus(IN PVOID ehciExtension, + IN PVOID ehciEndpoint, + IN ULONG EndpointStatus) +{ + PEHCI_ENDPOINT EhciEndpoint; + ULONG TransferType; + PEHCI_HCD_QH QH; + + EhciEndpoint = ehciEndpoint; + + DPRINT("EHCI_SetEndpointStatus: EhciEndpoint - %p, EndpointStatus - %x\n", + EhciEndpoint, + EndpointStatus); + + TransferType = EhciEndpoint->EndpointProperties.TransferType; + + if (TransferType != USBPORT_TRANSFER_TYPE_ISOCHRONOUS) + { + + if (EndpointStatus == USBPORT_ENDPOINT_RUN) + { + EhciEndpoint->EndpointStatus &= ~USBPORT_ENDPOINT_HALT; + + QH = EhciEndpoint->QH; + QH->sqh.HwQH.Token.Status &= (UCHAR)~EHCI_TOKEN_STATUS_HALTED; + + return; + } + + if (EndpointStatus == USBPORT_ENDPOINT_HALT) + DbgBreakPoint(); + } +} + +VOID +NTAPI +EHCI_ResetController(IN PVOID ehciExtension) +{ + DPRINT1("EHCI_ResetController: UNIMPLEMENTED. FIXME\n"); +} + +MPSTATUS +NTAPI +EHCI_StartSendOnePacket(IN PVOID ehciExtension, + IN PVOID PacketParameters, + IN PVOID Data, + IN PULONG pDataLength, + IN PVOID BufferVA, + IN PVOID BufferPA, + IN ULONG BufferLength, + IN USBD_STATUS * pUSBDStatus) +{ + DPRINT1("EHCI_StartSendOnePacket: UNIMPLEMENTED. FIXME\n"); + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_EndSendOnePacket(IN PVOID ehciExtension, + IN PVOID PacketParameters, + IN PVOID Data, + IN PULONG pDataLength, + IN PVOID BufferVA, + IN PVOID BufferPA, + IN ULONG BufferLength, + IN USBD_STATUS * pUSBDStatus) +{ + DPRINT1("EHCI_EndSendOnePacket: UNIMPLEMENTED. FIXME\n"); + return MP_STATUS_SUCCESS; +} + +MPSTATUS +NTAPI +EHCI_PassThru(IN PVOID ehciExtension, + IN PVOID passThruParameters, + IN ULONG ParameterLength, + IN PVOID pParameters) +{ + DPRINT1("EHCI_PassThru: UNIMPLEMENTED. FIXME\n"); + return MP_STATUS_SUCCESS; +} + +VOID +NTAPI +EHCI_RebalanceEndpoint(IN PVOID ohciExtension, + IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, + IN PVOID ohciEndpoint) +{ + DPRINT1("EHCI_RebalanceEndpoint: UNIMPLEMENTED. FIXME\n"); +} + +VOID +NTAPI +EHCI_FlushInterrupts(IN PVOID ehciExtension) +{ + PEHCI_EXTENSION EhciExtension = ehciExtension; + PEHCI_HW_REGISTERS OperationalRegs; + EHCI_USB_STATUS Status; + + DPRINT("EHCI_FlushInterrupts: ... \n"); + + OperationalRegs = EhciExtension->OperationalRegs; + + Status.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG); + WRITE_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG, Status.AsULONG); +} + +VOID +NTAPI +EHCI_TakePortControl(IN PVOID ohciExtension) +{ + DPRINT1("EHCI_TakePortControl: UNIMPLEMENTED. FIXME\n"); +} + +VOID +NTAPI +EHCI_Unload(IN PDRIVER_OBJECT DriverObject) +{ +#if DBG + DPRINT1("EHCI_Unload: Not supported\n"); +#endif + return; +} + +NTSTATUS +NTAPI +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + DPRINT("DriverEntry: DriverObject - %p, RegistryPath - %wZ\n", + DriverObject, + RegistryPath); + + if (USBPORT_GetHciMn() != USBPORT_HCI_MN) + return STATUS_INSUFFICIENT_RESOURCES; + + RtlZeroMemory(&RegPacket, sizeof(USBPORT_REGISTRATION_PACKET)); + + RegPacket.MiniPortVersion = USB_MINIPORT_VERSION_EHCI; + + RegPacket.MiniPortFlags = USB_MINIPORT_FLAGS_INTERRUPT | + USB_MINIPORT_FLAGS_MEMORY_IO | + USB_MINIPORT_FLAGS_USB2 | + USB_MINIPORT_FLAGS_POLLING | + USB_MINIPORT_FLAGS_WAKE_SUPPORT; + + RegPacket.MiniPortBusBandwidth = TOTAL_USB20_BUS_BANDWIDTH; + + RegPacket.MiniPortExtensionSize = sizeof(EHCI_EXTENSION); + RegPacket.MiniPortEndpointSize = sizeof(EHCI_ENDPOINT); + RegPacket.MiniPortTransferSize = sizeof(EHCI_TRANSFER); + RegPacket.MiniPortResourcesSize = sizeof(EHCI_HC_RESOURCES); + + RegPacket.OpenEndpoint = EHCI_OpenEndpoint; + RegPacket.ReopenEndpoint = EHCI_ReopenEndpoint; + RegPacket.QueryEndpointRequirements = EHCI_QueryEndpointRequirements; + RegPacket.CloseEndpoint = EHCI_CloseEndpoint; + RegPacket.StartController = EHCI_StartController; + RegPacket.StopController = EHCI_StopController; + RegPacket.SuspendController = EHCI_SuspendController; + RegPacket.ResumeController = EHCI_ResumeController; + RegPacket.InterruptService = EHCI_InterruptService; + RegPacket.InterruptDpc = EHCI_InterruptDpc; + RegPacket.SubmitTransfer = EHCI_SubmitTransfer; + RegPacket.SubmitIsoTransfer = EHCI_SubmitIsoTransfer; + RegPacket.AbortTransfer = EHCI_AbortTransfer; + RegPacket.GetEndpointState = EHCI_GetEndpointState; + RegPacket.SetEndpointState = EHCI_SetEndpointState; + RegPacket.PollEndpoint = EHCI_PollEndpoint; + RegPacket.CheckController = EHCI_CheckController; + RegPacket.Get32BitFrameNumber = EHCI_Get32BitFrameNumber; + RegPacket.InterruptNextSOF = EHCI_InterruptNextSOF; + RegPacket.EnableInterrupts = EHCI_EnableInterrupts; + RegPacket.DisableInterrupts = EHCI_DisableInterrupts; + RegPacket.PollController = EHCI_PollController; + RegPacket.SetEndpointDataToggle = EHCI_SetEndpointDataToggle; + RegPacket.GetEndpointStatus = EHCI_GetEndpointStatus; + RegPacket.SetEndpointStatus = EHCI_SetEndpointStatus; + RegPacket.RH_GetRootHubData = EHCI_RH_GetRootHubData; + RegPacket.RH_GetStatus = EHCI_RH_GetStatus; + RegPacket.RH_GetPortStatus = EHCI_RH_GetPortStatus; + RegPacket.RH_GetHubStatus = EHCI_RH_GetHubStatus; + RegPacket.RH_SetFeaturePortReset = EHCI_RH_SetFeaturePortReset; + RegPacket.RH_SetFeaturePortPower = EHCI_RH_SetFeaturePortPower; + RegPacket.RH_SetFeaturePortEnable = EHCI_RH_SetFeaturePortEnable; + RegPacket.RH_SetFeaturePortSuspend = EHCI_RH_SetFeaturePortSuspend; + RegPacket.RH_ClearFeaturePortEnable = EHCI_RH_ClearFeaturePortEnable; + RegPacket.RH_ClearFeaturePortPower = EHCI_RH_ClearFeaturePortPower; + RegPacket.RH_ClearFeaturePortSuspend = EHCI_RH_ClearFeaturePortSuspend; + RegPacket.RH_ClearFeaturePortEnableChange = EHCI_RH_ClearFeaturePortEnableChange; + RegPacket.RH_ClearFeaturePortConnectChange = EHCI_RH_ClearFeaturePortConnectChange; + RegPacket.RH_ClearFeaturePortResetChange = EHCI_RH_ClearFeaturePortResetChange; + RegPacket.RH_ClearFeaturePortSuspendChange = EHCI_RH_ClearFeaturePortSuspendChange; + RegPacket.RH_ClearFeaturePortOvercurrentChange = EHCI_RH_ClearFeaturePortOvercurrentChange; + RegPacket.RH_DisableIrq = EHCI_RH_DisableIrq; + RegPacket.RH_EnableIrq = EHCI_RH_EnableIrq; ... 381 lines suppressed ...
6 years, 3 months
1
0
0
0
03/03: [SERVICES] Only services starting under the LocalSystem account can run interactively. Otherwise ignore the interactive flag.
by Hermès Bélusca-Maïto
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=419e0146756d50a6053b7…
commit 419e0146756d50a6053b7f2e01fd4660149b57b9 Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> AuthorDate: Sun Sep 9 22:20:38 2018 +0200 Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> CommitDate: Sun Sep 9 23:24:08 2018 +0200 [SERVICES] Only services starting under the LocalSystem account can run interactively. Otherwise ignore the interactive flag. --- base/system/services/database.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/base/system/services/database.c b/base/system/services/database.c index 409fab4c71..c4c372c320 100644 --- a/base/system/services/database.c +++ b/base/system/services/database.c @@ -1672,14 +1672,6 @@ ScmStartUserModeService(PSERVICE Service, StartupInfo.cb = sizeof(StartupInfo); ZeroMemory(&ProcessInformation, sizeof(ProcessInformation)); - /* Use the interactive desktop if the service is interactive */ - if ((NoInteractiveServices == 0) && - (Service->Status.dwServiceType & SERVICE_INTERACTIVE_PROCESS)) - { - StartupInfo.dwFlags |= STARTF_INHERITDESKTOP; - StartupInfo.lpDesktop = L"WinSta0\\Default"; - } - if (Service->lpImage->hToken) { /* User token: Run the service under the user account */ @@ -1732,6 +1724,14 @@ ScmStartUserModeService(PSERVICE Service, lpEnvironment = NULL; } + /* Use the interactive desktop if the service is interactive */ + if ((NoInteractiveServices == 0) && + (Service->Status.dwServiceType & SERVICE_INTERACTIVE_PROCESS)) + { + StartupInfo.dwFlags |= STARTF_INHERITDESKTOP; + StartupInfo.lpDesktop = L"WinSta0\\Default"; + } + Result = CreateProcessW(NULL, Service->lpImage->pszImagePath, NULL,
6 years, 3 months
1
0
0
0
02/03: [SERVICES] Re-implement RChangeServiceConfigA() around RChangeServiceConfigW(), much as what is done for RCreateServiceA().
by Hermès Bélusca-Maïto
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=cccf26da74008561f184a…
commit cccf26da74008561f184ac379b957bdb7000ac39 Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> AuthorDate: Sun Sep 9 22:14:57 2018 +0200 Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> CommitDate: Sun Sep 9 23:24:04 2018 +0200 [SERVICES] Re-implement RChangeServiceConfigA() around RChangeServiceConfigW(), much as what is done for RCreateServiceA(). --- base/system/services/rpcserver.c | 342 +++++++++------------------------------ 1 file changed, 73 insertions(+), 269 deletions(-) diff --git a/base/system/services/rpcserver.c b/base/system/services/rpcserver.c index 3c5af07499..ae6c721410 100644 --- a/base/system/services/rpcserver.c +++ b/base/system/services/rpcserver.c @@ -2019,6 +2019,7 @@ RChangeServiceConfigW( goto done; /* Write service data to the registry */ + /* Set the display name */ if (lpDisplayName != NULL && *lpDisplayName != 0) { @@ -3412,310 +3413,113 @@ RChangeServiceConfigA( LPSTR lpDisplayName) { DWORD dwError = ERROR_SUCCESS; - PSERVICE_HANDLE hSvc; - PSERVICE lpService = NULL; - HKEY hServiceKey = NULL; - LPWSTR lpDisplayNameW = NULL; LPWSTR lpBinaryPathNameW = NULL; - LPWSTR lpCanonicalImagePathW = NULL; LPWSTR lpLoadOrderGroupW = NULL; LPWSTR lpDependenciesW = NULL; + LPWSTR lpServiceStartNameW = NULL; + LPWSTR lpDisplayNameW = NULL; + DWORD dwDependenciesLength = 0; + SIZE_T cchLength; + int len; + LPCSTR lpStr; - DPRINT("RChangeServiceConfigA() called\n"); - DPRINT("dwServiceType = %lu\n", dwServiceType); - DPRINT("dwStartType = %lu\n", dwStartType); - DPRINT("dwErrorControl = %lu\n", dwErrorControl); - DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName); - DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup); - DPRINT("lpDisplayName = %s\n", lpDisplayName); - - if (ScmShutdown) - return ERROR_SHUTDOWN_IN_PROGRESS; - - hSvc = ScmGetServiceFromHandle(hService); - if (hSvc == NULL) - { - DPRINT1("Invalid service handle!\n"); - return ERROR_INVALID_HANDLE; - } - - if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, - SERVICE_CHANGE_CONFIG)) - { - DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); - return ERROR_ACCESS_DENIED; - } - - lpService = hSvc->ServiceEntry; - if (lpService == NULL) - { - DPRINT("lpService == NULL!\n"); - return ERROR_INVALID_HANDLE; - } - - /* Lock the service database exclusively */ - ScmLockDatabaseExclusive(); - - if (lpService->bDeleted) - { - DPRINT("The service has already been marked for delete!\n"); - dwError = ERROR_SERVICE_MARKED_FOR_DELETE; - goto done; - } - - /* Open the service key */ - dwError = ScmOpenServiceKey(lpService->szServiceName, - KEY_SET_VALUE, - &hServiceKey); - if (dwError != ERROR_SUCCESS) - goto done; - - /* Write service data to the registry */ - - if (lpDisplayName != NULL && *lpDisplayName != 0) + if (lpBinaryPathName) { - /* Set the display name */ - lpDisplayNameW = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - (strlen(lpDisplayName) + 1) * sizeof(WCHAR)); - if (lpDisplayNameW == NULL) + len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0); + lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); + if (!lpBinaryPathNameW) { - dwError = ERROR_NOT_ENOUGH_MEMORY; - goto done; + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; } - - MultiByteToWideChar(CP_ACP, - 0, - lpDisplayName, - -1, - lpDisplayNameW, - (int)(strlen(lpDisplayName) + 1)); - - RegSetValueExW(hServiceKey, - L"DisplayName", - 0, - REG_SZ, - (LPBYTE)lpDisplayNameW, - (DWORD)((wcslen(lpDisplayNameW) + 1) * sizeof(WCHAR))); - - /* Update lpService->lpDisplayName */ - if (lpService->lpDisplayName) - HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName); - - lpService->lpDisplayName = lpDisplayNameW; - } - - if (dwServiceType != SERVICE_NO_CHANGE) - { - /* Set the service type */ - dwError = RegSetValueExW(hServiceKey, - L"Type", - 0, - REG_DWORD, - (LPBYTE)&dwServiceType, - sizeof(DWORD)); - if (dwError != ERROR_SUCCESS) - goto done; - - lpService->Status.dwServiceType = dwServiceType; - } - - if (dwStartType != SERVICE_NO_CHANGE) - { - /* Set the start value */ - dwError = RegSetValueExW(hServiceKey, - L"Start", - 0, - REG_DWORD, - (LPBYTE)&dwStartType, - sizeof(DWORD)); - if (dwError != ERROR_SUCCESS) - goto done; - - lpService->dwStartType = dwStartType; - } - - if (dwErrorControl != SERVICE_NO_CHANGE) - { - /* Set the error control value */ - dwError = RegSetValueExW(hServiceKey, - L"ErrorControl", - 0, - REG_DWORD, - (LPBYTE)&dwErrorControl, - sizeof(DWORD)); - if (dwError != ERROR_SUCCESS) - goto done; - - lpService->dwErrorControl = dwErrorControl; + MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, len); } - if (lpBinaryPathName != NULL && *lpBinaryPathName != 0) + if (lpLoadOrderGroup) { - /* Set the image path */ - lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - (strlen(lpBinaryPathName) + 1) * sizeof(WCHAR)); - if (lpBinaryPathNameW == NULL) - { - dwError = ERROR_NOT_ENOUGH_MEMORY; - goto done; - } - - MultiByteToWideChar(CP_ACP, - 0, - lpBinaryPathName, - -1, - lpBinaryPathNameW, - (int)(strlen(lpBinaryPathName) + 1)); - - if (lpService->Status.dwServiceType & SERVICE_DRIVER) + len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0); + lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); + if (!lpLoadOrderGroupW) { - dwError = ScmCanonDriverImagePath(lpService->dwStartType, - lpBinaryPathNameW, - &lpCanonicalImagePathW); - - HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW); - - if (dwError != ERROR_SUCCESS) - goto done; - - lpBinaryPathNameW = lpCanonicalImagePathW; + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; } - - dwError = RegSetValueExW(hServiceKey, - L"ImagePath", - 0, - REG_EXPAND_SZ, - (LPBYTE)lpBinaryPathNameW, - (DWORD)((wcslen(lpBinaryPathNameW) + 1) * sizeof(WCHAR))); - - HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW); - - if (dwError != ERROR_SUCCESS) - goto done; + MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len); } - /* Set the group name */ - if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0) + if (lpDependencies) { - lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - (strlen(lpLoadOrderGroup) + 1) * sizeof(WCHAR)); - if (lpLoadOrderGroupW == NULL) + lpStr = (LPCSTR)lpDependencies; + while (*lpStr) { - dwError = ERROR_NOT_ENOUGH_MEMORY; - goto done; + cchLength = strlen(lpStr) + 1; + dwDependenciesLength += (DWORD)cchLength; + lpStr = lpStr + cchLength; } + dwDependenciesLength++; - MultiByteToWideChar(CP_ACP, - 0, - lpLoadOrderGroup, - -1, - lpLoadOrderGroupW, - (int)(strlen(lpLoadOrderGroup) + 1)); - - dwError = RegSetValueExW(hServiceKey, - L"Group", - 0, - REG_SZ, - (LPBYTE)lpLoadOrderGroupW, - (DWORD)((wcslen(lpLoadOrderGroupW) + 1) * sizeof(WCHAR))); - if (dwError != ERROR_SUCCESS) + lpDependenciesW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDependenciesLength * sizeof(WCHAR)); + if (!lpDependenciesW) { - HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW); - goto done; + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; } - - dwError = ScmSetServiceGroup(lpService, - lpLoadOrderGroupW); - - HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW); - - if (dwError != ERROR_SUCCESS) - goto done; + MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength); } - if (lpdwTagId != NULL) + if (lpServiceStartName) { - dwError = ScmAssignNewTag(lpService); - if (dwError != ERROR_SUCCESS) - goto done; - - dwError = RegSetValueExW(hServiceKey, - L"Tag", - 0, - REG_DWORD, - (LPBYTE)&lpService->dwTag, - sizeof(DWORD)); - if (dwError != ERROR_SUCCESS) - goto done; - - *lpdwTagId = lpService->dwTag; + len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0); + lpServiceStartNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); + if (!lpServiceStartNameW) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; + } + MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len); } - /* Write dependencies */ - if (lpDependencies != NULL && *lpDependencies != 0) + if (lpDisplayName) { - lpDependenciesW = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - (strlen((LPSTR)lpDependencies) + 1) * sizeof(WCHAR)); - if (lpDependenciesW == NULL) + len = MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, NULL, 0); + lpDisplayNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); + if (!lpDisplayNameW) { - dwError = ERROR_NOT_ENOUGH_MEMORY; - goto done; + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; } - - MultiByteToWideChar(CP_ACP, - 0, - (LPSTR)lpDependencies, - dwDependSize, - lpDependenciesW, - (int)(strlen((LPSTR)lpDependencies) + 1)); - - dwError = ScmWriteDependencies(hServiceKey, - (LPWSTR)lpDependenciesW, - dwDependSize); - - HeapFree(GetProcessHeap(), 0, lpDependenciesW); - - if (dwError != ERROR_SUCCESS) - goto done; + MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len); } - if (lpPassword != NULL) - { - if (wcslen((LPWSTR)lpPassword) != 0) - { - /* FIXME: Decrypt the password */ + dwError = RChangeServiceConfigW(hService, + dwServiceType, + dwStartType, + dwErrorControl, + lpBinaryPathNameW, + lpLoadOrderGroupW, + lpdwTagId, + (LPBYTE)lpDependenciesW, + dwDependenciesLength, + lpServiceStartNameW, + lpPassword, + dwPwSize, + lpDisplayNameW); - /* Write the password */ - dwError = ScmSetServicePassword(lpService->szServiceName, - (LPCWSTR)lpPassword); - if (dwError != ERROR_SUCCESS) - goto done; - } - else - { - /* Delete the password */ - dwError = ScmSetServicePassword(lpService->szServiceName, - NULL); - if (dwError == ERROR_FILE_NOT_FOUND) - dwError = ERROR_SUCCESS; +cleanup: + if (lpBinaryPathNameW != NULL) + HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW); - if (dwError != ERROR_SUCCESS) - goto done; - } - } + if (lpLoadOrderGroupW != NULL) + HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW); -done: - /* Unlock the service database */ - ScmUnlockDatabase(); + if (lpDependenciesW != NULL) + HeapFree(GetProcessHeap(), 0, lpDependenciesW); - if (hServiceKey != NULL) - RegCloseKey(hServiceKey); + if (lpServiceStartNameW != NULL) + HeapFree(GetProcessHeap(), 0, lpServiceStartNameW); - DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError); + if (lpDisplayNameW != NULL) + HeapFree(GetProcessHeap(), 0, lpDisplayNameW); return dwError; }
6 years, 3 months
1
0
0
0
01/03: [SERVICES] RChangeServiceConfigW: Check valid usage of lpdwTagId when lpLoadOrderGroup is not specified.
by Hermès Bélusca-Maïto
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d6e577ced93fb03fa171f…
commit d6e577ced93fb03fa171fb10f6d22ac7802a7587 Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> AuthorDate: Sun Sep 9 20:52:36 2018 +0200 Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> CommitDate: Sun Sep 9 23:23:55 2018 +0200 [SERVICES] RChangeServiceConfigW: Check valid usage of lpdwTagId when lpLoadOrderGroup is not specified. --- base/system/services/rpcserver.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/base/system/services/rpcserver.c b/base/system/services/rpcserver.c index 351793736d..3c5af07499 100644 --- a/base/system/services/rpcserver.c +++ b/base/system/services/rpcserver.c @@ -1989,6 +1989,11 @@ RChangeServiceConfigW( (dwErrorControl != SERVICE_ERROR_CRITICAL)) return ERROR_INVALID_PARAMETER; + if (lpdwTagId && (!lpLoadOrderGroup || !*lpLoadOrderGroup)) + { + return ERROR_INVALID_PARAMETER; + } + lpService = hSvc->ServiceEntry; if (lpService == NULL) {
6 years, 3 months
1
0
0
0
01/01: [NET] Update Russian translation (#849)
by Stanislav Motylkov
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=dcd4a3d000f8653386ca7…
commit dcd4a3d000f8653386ca715a27516d386dc4688a Author: Stanislav Motylkov <x86corez(a)gmail.com> AuthorDate: Mon Sep 10 00:11:11 2018 +0300 Commit: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito(a)reactos.org> CommitDate: Sun Sep 9 23:11:11 2018 +0200 [NET] Update Russian translation (#849) --- base/applications/network/net/lang/ru-RU.rc | 124 ++++++++++++++-------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/base/applications/network/net/lang/ru-RU.rc b/base/applications/network/net/lang/ru-RU.rc index 69b275a275..b9a14f7ed4 100644 --- a/base/applications/network/net/lang/ru-RU.rc +++ b/base/applications/network/net/lang/ru-RU.rc @@ -202,72 +202,72 @@ service can stop others. Some services cannot be stopped.\n\n" IDS_ACCOUNTS_STANDALONE_SERVER "Автономный сервер" IDS_ACCOUNTS_WORKSTATION "Рабочая станция" - IDS_CONFIG_TEXT "The following running services can be controlled:\n\n\ - Server\n Workstation\n\n" - IDS_CONFIG_SERVER_NAME "Server Name" - IDS_CONFIG_SERVER_COMMENT "Server Comment" - IDS_CONFIG_SERVER_VERSION "Software version" - IDS_CONFIG_SERVER_ACTIVE "Server is active on" - IDS_CONFIG_SERVER_HIDDEN "Server hidden" - IDS_CONFIG_SERVER_USERS "Maximum Logged On Users" - IDS_CONFIG_SERVER_FILES "Maximum open files per session" - IDS_CONFIG_SERVER_IDLE "Idle session time (min)" - IDS_CONFIG_WORKSTATION_NAME "Computer name" - IDS_CONFIG_WORKSTATION_FULLNAME "Full Computer name" - IDS_CONFIG_WORKSTATION_USERNAME "User name" - IDS_CONFIG_WORKSTATION_ACTIVE "Workstation is active on" - IDS_CONFIG_WORKSTATION_VERSION "Software version" - IDS_CONFIG_WORKSTATION_DOMAIN "Workstation domain" - IDS_CONFIG_WORKSTATION_LOGON "Logon domain" + IDS_CONFIG_TEXT "Можно управлять следующими выполняющимися службами:\n\n\ + Сервер\n Рабочая станция\n\n" + IDS_CONFIG_SERVER_NAME "Имя сервера" + IDS_CONFIG_SERVER_COMMENT "Комментарий для сервера" + IDS_CONFIG_SERVER_VERSION "Версия программы" + IDS_CONFIG_SERVER_ACTIVE "Активный сервер на" + IDS_CONFIG_SERVER_HIDDEN "Скрытый сервер" + IDS_CONFIG_SERVER_USERS "Максимальное число пользователей" + IDS_CONFIG_SERVER_FILES "Максимальное число открытых файлов в сеансе" + IDS_CONFIG_SERVER_IDLE "Время простоя сеанса (мин)" + IDS_CONFIG_WORKSTATION_NAME "Имя компьютера" + IDS_CONFIG_WORKSTATION_FULLNAME "Полное имя компьютера" + IDS_CONFIG_WORKSTATION_USERNAME "Имя пользователя" + IDS_CONFIG_WORKSTATION_ACTIVE "Активная рабочая станция на" + IDS_CONFIG_WORKSTATION_VERSION "Версия программы" + IDS_CONFIG_WORKSTATION_DOMAIN "Домен рабочей станции" + IDS_CONFIG_WORKSTATION_LOGON "Домен входа" - IDS_GROUP_GROUPS "Group Accounts for \\\\%s" - IDS_GROUP_NAME "Group name" - IDS_GROUP_COMMENT "Comment" - IDS_GROUP_MEMBERS "Members" + IDS_GROUP_GROUPS "Учетные записи групп для \\\\%s" + IDS_GROUP_NAME "Имя группы" + IDS_GROUP_COMMENT "Комментарий" + IDS_GROUP_MEMBERS "Члены" IDS_LOCALGROUP_ALIASES "Псевдонимы для \\\\%s" IDS_LOCALGROUP_ALIAS_NAME "Имя псевдонима" IDS_LOCALGROUP_COMMENT "Комментарий" IDS_LOCALGROUP_MEMBERS "Члены" - IDS_STATISTICS_TEXT "Statistics are available for the following services:\n\n\ - Server\n Workstation\n\n" - IDS_STATISTICS_SINCE "Statistics since %d/%d/%d %d:%02d %s\n\n\n" - IDS_STATISTICS_SRV_NAME "Server statistics for \\\\%s\n\n\n" - IDS_STATISTICS_SRV_SESACCEPT "Sessions accepted" - IDS_STATISTICS_SRV_SESSTIME "Sessions timed-out" - IDS_STATISTICS_SRV_SESSERROR "Sessions errored-out" - IDS_STATISTICS_SRV_KBSENT "Kilobytes sent" - IDS_STATISTICS_SRV_KBRCVD "Kilobytes received" - IDS_STATISTICS_SRV_MRESPTIME "Mean response time (msec)" - IDS_STATISTICS_SRV_SYSERRORS "System errors" - IDS_STATISTICS_SRV_PMERRORS "Permission violations" - IDS_STATISTICS_SRV_PWERRORS "Password violations" - IDS_STATISTICS_SRV_FILES "Files accessed" - IDS_STATISTICS_SRV_DEVICES "Communication devices accessed" - IDS_STATISTICS_SRV_JOBS "Print jobs spooled" - IDS_STATISTICS_SRV_BUFFERS "Times buffers exhausted\n\n" - IDS_STATISTICS_SRV_BIGBUFFERS " Big buffers" - IDS_STATISTICS_SRV_REQBUFFERS " Request buffers" - IDS_STATISTICS_WKS_NAME "Workstation statistics for \\\\%s\n\n\n" - IDS_STATISTICS_WKS_BYTESRCVD "Bytes received" - IDS_STATISTICS_WKS_SMBSRCVD "Server Message Blocks (SMBs) received" - IDS_STATISTICS_WKS_BYTESTRANS "Bytes transmitted" - IDS_STATISTICS_WKS_SMBSTRANS "Server Message Blocks (SMBs) transmitted" - IDS_STATISTICS_WKS_READOPS "Read operations" - IDS_STATISTICS_WKS_WRITEOPS "Write operations" - IDS_STATISTICS_WKS_READDENIED "Raw reads denied" - IDS_STATISTICS_WKS_WRITEDENIED "Raw writes denied" - IDS_STATISTICS_WKS_NETWORKERROR "Network errors" - IDS_STATISTICS_WKS_CONNECTS "Connections made" - IDS_STATISTICS_WKS_RECONNECTS "Reconnections made" - IDS_STATISTICS_WKS_DISCONNECTS "Server disconnects" - IDS_STATISTICS_WKS_SESSIONS "Sessions started" - IDS_STATISTICS_WKS_HUNGSESSIONS "Hung sessions" - IDS_STATISTICS_WKS_FAILSESSIONS "Failed sessions" - IDS_STATISTICS_WKS_FAILEDOPS "Failed operations" - IDS_STATISTICS_WKS_USECOUNT "Use count" - IDS_STATISTICS_WKS_FAILUSECOUNT "Failed use count" + IDS_STATISTICS_TEXT "Статистика доступна для следующих выполняющихся служб:\n\n\ + Сервер\n Рабочая станция\n\n" + IDS_STATISTICS_SINCE "Статистика после %d/%d/%d %d:%02d %s\n\n\n" + IDS_STATISTICS_SRV_NAME "Статистика сервера для \\\\%s\n\n\n" + IDS_STATISTICS_SRV_SESACCEPT "Принятые сеансы" + IDS_STATISTICS_SRV_SESSTIME "Сеансы с истекшим интервалом" + IDS_STATISTICS_SRV_SESSERROR "Сеансы с ошибками" + IDS_STATISTICS_SRV_KBSENT "Послано КБ" + IDS_STATISTICS_SRV_KBRCVD "Принято КБ" + IDS_STATISTICS_SRV_MRESPTIME "Среднее время отклика (мс)" + IDS_STATISTICS_SRV_SYSERRORS "Системные ошибки" + IDS_STATISTICS_SRV_PMERRORS "Нарушение разрешений" + IDS_STATISTICS_SRV_PWERRORS "Нарушение паролей" + IDS_STATISTICS_SRV_FILES "Доступ к файлам" + IDS_STATISTICS_SRV_DEVICES "Доступ к устройствам связи" + IDS_STATISTICS_SRV_JOBS "Задания печати в очереди" + IDS_STATISTICS_SRV_BUFFERS "Исчерпанные буферы времени\n\n" + IDS_STATISTICS_SRV_BIGBUFFERS " Большие буферы" + IDS_STATISTICS_SRV_REQBUFFERS " Затребованные буферы" + IDS_STATISTICS_WKS_NAME "Статистика рабочей станции для \\\\%s\n\n\n" + IDS_STATISTICS_WKS_BYTESRCVD "Получено байт" + IDS_STATISTICS_WKS_SMBSRCVD "Принятые блоки сообщений сервера SMB" + IDS_STATISTICS_WKS_BYTESTRANS "Передано байт" + IDS_STATISTICS_WKS_SMBSTRANS "Переданные блоки сообщений сервера SMB" + IDS_STATISTICS_WKS_READOPS "Операции чтения" + IDS_STATISTICS_WKS_WRITEOPS "Операции записи" + IDS_STATISTICS_WKS_READDENIED "Отказано в чтении" + IDS_STATISTICS_WKS_WRITEDENIED "Отказано в записи" + IDS_STATISTICS_WKS_NETWORKERROR "Ошибки сети" + IDS_STATISTICS_WKS_CONNECTS "Выполненные подключения" + IDS_STATISTICS_WKS_RECONNECTS "Повторные подключения" + IDS_STATISTICS_WKS_DISCONNECTS "Отключений от сервера" + IDS_STATISTICS_WKS_SESSIONS "Запущенные сеансы" + IDS_STATISTICS_WKS_HUNGSESSIONS "Зависание сеансов" + IDS_STATISTICS_WKS_FAILSESSIONS "Сбои в сеансах" + IDS_STATISTICS_WKS_FAILEDOPS "Сбои в операциях" + IDS_STATISTICS_WKS_USECOUNT "Счетчик использования" + IDS_STATISTICS_WKS_FAILUSECOUNT "Счетчик сбоев при использовании" IDS_USER_ACCOUNTS "Учетные записи пользователей для \\\\%s" IDS_USER_NAME "Имя пользователя" @@ -303,9 +303,9 @@ service can stop others. Some services cannot be stopped.\n\n" IDS_GENERIC_NONE "Нет" IDS_GENERIC_ALL "Все" IDS_GENERIC_LOCKED "Заблокировано" - IDS_GENERIC_UNLIMITED "Unlimited" - IDS_GENERIC_SYNTAX "The syntax of this command is:\n\n" - IDS_GENERIC_PAGE "NET HELP command | MORE displays one screen at a time.\n\n" + IDS_GENERIC_UNLIMITED "Не ограничено" + IDS_GENERIC_SYNTAX "Синтаксис данной команды:\n\n" + IDS_GENERIC_PAGE "NET HELP имя_команды | MORE - постраничный просмотр справки.\n\n" IDS_ERROR_OPTION_NOT_SUPPORTED "Опция %s в данный момент не поддерживается.\n" IDS_ERROR_INVALID_OPTION_VALUE "Вы ввели неверный данные для данной опции %s.\n"
6 years, 3 months
1
0
0
0
← Newer
1
...
13
14
15
16
17
18
19
...
23
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Results per page:
10
25
50
100
200