replace nob with ms' build, move disk creation to build.bat, major comment cleanup, remove old and stupid tests, overhaul interrupt management with per-CPU vector allocation, affinity migration and safe teardown, add proper IOAPIC routing and PCI MSI/MSI-X/INTx support, migrate drivers to the new interrupt API, integrate ACPICA with a proper OS services layer, move ACPI firmware events, power button handling and S5 shutdown into acpi.sys, add parallel driver startup and atomic publication, replace PnP arrays with dynamic lists, redesign service startup again to be asynchronous, add delayed startup mode for services, allow omitting keys in services.ini, fix acpi ec deferred work handling, fix kernel threads having garbage exit code.
This commit is contained in:
1 parent
d36f19509c
commit
36eef8f58d
696 files changed
+147281
-7530
No files matched your search
+15
-6
@@ -1,9 +1,18 @@
|
|||||||
build.obj
|
|
||||||
bin/
|
bin/
|
||||||
obj/
|
sdktools/out/
|
||||||
|
|
||||||
|
*.vhd
|
||||||
|
*.vhdx
|
||||||
|
*.iso
|
||||||
|
*.img
|
||||||
|
*.bin
|
||||||
|
*.log
|
||||||
|
*.zip
|
||||||
|
|
||||||
qemu.log
|
qemu.log
|
||||||
disk.vhd
|
|
||||||
usbfatroot/
|
usbfatroot/
|
||||||
code.zip
|
|
||||||
code/build/build.exe
|
**/obj/
|
||||||
code/build/build.exe.old
|
build.dat
|
||||||
|
|
||||||
|
.vscode/
|
||||||
Binary file not shown.
@@ -1,9 +1,134 @@
|
|||||||
@echo off
|
@echo off
|
||||||
:: If the build system binary doesn't exist, bootstrap it!
|
setlocal EnableExtensions DisableDelayedExpansion
|
||||||
if not exist "code\build\build.exe" (
|
pushd "%~dp0" || exit /b 1
|
||||||
echo Bootstrapping build system...
|
|
||||||
cl.exe /nologo /Fe"code\build\build.exe" "code\build\build.c"
|
if not exist "sdktools\out\build.exe" (
|
||||||
|
call "sdktools\build.bat"
|
||||||
|
if errorlevel 1 goto :fail
|
||||||
|
)
|
||||||
|
rem BUILD scans includes separately from the NMAKE compiler flags.
|
||||||
|
set "INCLUDE=%CD%\code\public;%CD%\code\common\include;%INCLUDE%"
|
||||||
|
"sdktools\out\build.exe" %*
|
||||||
|
if errorlevel 1 goto :fail
|
||||||
|
if /I "%NTL_SKIP_VHD%"=="1" goto :done
|
||||||
|
|
||||||
|
for %%T in (mformat mdir mmd mcopy) do (
|
||||||
|
where %%T >nul 2>&1
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo Missing mtools utility: %%T 1>&2
|
||||||
|
goto :fail
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
:: Run the build system, passing any args along
|
if exist "disk.vhd" (
|
||||||
"code\build\build.exe" %*
|
call :ValidateVhd || goto :fail
|
||||||
|
) else (
|
||||||
|
call :CreateVhd || goto :fail
|
||||||
|
)
|
||||||
|
|
||||||
|
set "ESP=disk.vhd@@1M"
|
||||||
|
set "SYS=disk.vhd@@65M"
|
||||||
|
for %%D in (EFI EFI/BOOT EFI/NTLite EFI/NTLite/fs) do (
|
||||||
|
call :EnsureDir "%ESP%" "%%D" || goto :fail
|
||||||
|
)
|
||||||
|
for %%D in (apps system drivers) do (
|
||||||
|
call :EnsureDir "%SYS%" "%%D" || goto :fail
|
||||||
|
)
|
||||||
|
|
||||||
|
call :CopyFat "bin\bootx64.efi" "%ESP%" "EFI/BOOT/bootx64.efi" || goto :fail
|
||||||
|
call :CopyFat "code\boot.ini" "%ESP%" "boot.ini" || goto :fail
|
||||||
|
for %%F in ("code\boot\uefi\fs\*.efi") do (
|
||||||
|
if exist "%%~fF" (
|
||||||
|
call :CopyFat "%%~fF" "%ESP%" "EFI/NTLite/fs/%%~nxF" || goto :fail
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
call :CopyFat "bin\kernel.exe" "%SYS%" "system/colonel.exe" || goto :fail
|
||||||
|
for %%F in (
|
||||||
|
bin\hal.dll bin\syscall.dll bin\win32.dll bin\posix.dll
|
||||||
|
bin\init.exe bin\rssrv.exe bin\posixsrv.exe bin\dwm.exe
|
||||||
|
code\settings.ini code\services.ini
|
||||||
|
) do (
|
||||||
|
call :CopyFat "%%F" "%SYS%" "system/%%~nxF" || goto :fail
|
||||||
|
)
|
||||||
|
for %%F in (
|
||||||
|
bin\pci.sys bin\ps2.sys bin\hda.sys bin\ata.sys bin\ahci.sys
|
||||||
|
bin\fat.sys bin\ntfs.sys bin\ext4.sys bin\vmwaresvga.sys
|
||||||
|
bin\lwip.sys bin\usb.sys bin\acpi.sys bin\rtl816x.sys bin\rtl8139.sys
|
||||||
|
code\drivers.ini
|
||||||
|
) do (
|
||||||
|
call :CopyFat "%%F" "%SYS%" "drivers/%%~nxF" || goto :fail
|
||||||
|
)
|
||||||
|
call :CopyFat "bin\serial.sys" "%SYS%" "drivers/cereal.sys" || goto :fail
|
||||||
|
for %%F in (
|
||||||
|
bin\shell_win32.exe bin\shell_posix.exe bin\shell_native.exe
|
||||||
|
bin\edit.exe bin\httpget.exe bin\tcpserve.exe bin\udp.exe
|
||||||
|
bin\resolve.exe bin\ping.exe bin\doom.exe bin\video.exe bin\memtop.exe
|
||||||
|
) do (
|
||||||
|
call :CopyFat "%%F" "%SYS%" "apps/%%~nxF" || goto :fail
|
||||||
|
)
|
||||||
|
for %%F in (
|
||||||
|
code\user\apps\video\bink2w64.dll
|
||||||
|
code\user\apps\video\video.bk2
|
||||||
|
code\user\apps\doom\doom1.wad
|
||||||
|
) do (
|
||||||
|
if exist "%%F" (
|
||||||
|
call :CopyFat "%%F" "%SYS%" "apps/%%~nxF" || goto :fail
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if /I "%NTL_WITH_TESTS%"=="1" (
|
||||||
|
call :EnsureDir "%SYS%" "tests" || goto :fail
|
||||||
|
for /D %%D in ("code\user\tests\*") do (
|
||||||
|
if exist "%%~fD\sources" (
|
||||||
|
call :CopyFat "bin\%%~nxD.exe" "%SYS%" "tests/%%~nxD.exe" || goto :fail
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
echo Updated disk.vhd
|
||||||
|
:done
|
||||||
|
popd
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:fail
|
||||||
|
echo Build or VHD packaging failed. 1>&2
|
||||||
|
popd
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:EnsureDir
|
||||||
|
mdir -i "%~1" "::%~2" >nul 2>&1
|
||||||
|
if not errorlevel 1 exit /b 0
|
||||||
|
mmd -i "%~1" "::%~2"
|
||||||
|
exit /b %errorlevel%
|
||||||
|
|
||||||
|
:CopyFat
|
||||||
|
if not exist "%~1" (
|
||||||
|
echo Missing build artifact: %~1 1>&2
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
mcopy -o -i "%~2" "%~1" "::%~3"
|
||||||
|
exit /b %errorlevel%
|
||||||
|
|
||||||
|
:ValidateVhd
|
||||||
|
powershell -NoProfile -Command "$ErrorActionPreference='Stop'; $f=[IO.File]::OpenRead('disk.vhd'); try { $m=New-Object byte[] 512; if ($f.Length -ne 536871424 -or $f.Read($m,0,512) -ne 512) {throw 'Unexpected VHD size'}; if ([BitConverter]::ToUInt32($m,440) -ne 0x4E544C31 -or $m[510] -ne 85 -or $m[511] -ne 170) {throw 'Unexpected disk signature'}; if ([BitConverter]::ToUInt32($m,454) -ne 2048 -or [BitConverter]::ToUInt32($m,458) -ne 131072 -or [BitConverter]::ToUInt32($m,470) -ne 133120 -or [BitConverter]::ToUInt32($m,474) -ne 524288) {throw 'Unexpected partition layout'}; $f.Position=536870912; $v=New-Object byte[] 512; if ($f.Read($v,0,512) -ne 512 -or [Text.Encoding]::ASCII.GetString($v,0,8) -ne 'conectix') {throw 'Invalid VHD footer'} } finally {$f.Dispose()}"
|
||||||
|
exit /b %errorlevel%
|
||||||
|
|
||||||
|
:CreateVhd
|
||||||
|
if exist "disk.vhd.new" (
|
||||||
|
echo disk.vhd.new already exists; resolve it before initializing a disk. 1>&2
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
echo Creating 512 MiB fixed VHD...
|
||||||
|
powershell -NoProfile -Command "$ErrorActionPreference='Stop'; function Be([byte[]]$a,[int]$o,[uint64]$v,[int]$n) {for($i=0;$i -lt $n;$i++) {$a[$o+$i]=[byte](($v -shr (8*($n-$i-1))) -band 255)}}; $s=[IO.File]::Open('disk.vhd.new',[IO.FileMode]::CreateNew,[IO.FileAccess]::ReadWrite); try { $s.SetLength(536871424); $m=New-Object byte[] 512; [BitConverter]::GetBytes([uint32]0x4E544C31).CopyTo($m,440); $m[510]=85; $m[511]=170; [byte[]]$p=0x80,0,2,0,12,254,255,255; [Array]::Copy($p,0,$m,446,8); [BitConverter]::GetBytes([uint32]2048).CopyTo($m,454); [BitConverter]::GetBytes([uint32]131072).CopyTo($m,458); [byte[]]$p=0,0,1,8,12,254,255,255; [Array]::Copy($p,0,$m,462,8); [BitConverter]::GetBytes([uint32]133120).CopyTo($m,470); [BitConverter]::GetBytes([uint32]524288).CopyTo($m,474); $s.Write($m,0,512); $v=New-Object byte[] 512; [Text.Encoding]::ASCII.GetBytes('conectix').CopyTo($v,0); $v[11]=2; $v[13]=1; for($i=16;$i -lt 24;$i++) {$v[$i]=255}; [Text.Encoding]::ASCII.GetBytes('qemu').CopyTo($v,28); $v[33]=2; [Text.Encoding]::ASCII.GetBytes('Wi2k').CopyTo($v,36); Be $v 40 ([uint64]536870912) 8; Be $v 48 ([uint64]536870912) 8; $v[56]=4; $v[58]=16; $v[59]=63; $v[63]=2; [byte[]]$id=0xA1,0xB2,0xC3,0xD4,0xE5,0xF6,0x78,0x90,0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0; [Array]::Copy($id,0,$v,68,16); $sum=0; foreach($b in $v) {$sum+=$b}; Be $v 64 ([uint64]([uint32]::MaxValue - [uint32]$sum)) 4; $s.Position=536870912; $s.Write($v,0,512) } finally {$s.Dispose()}"
|
||||||
|
if errorlevel 1 goto :CreateFailed
|
||||||
|
mformat -i "disk.vhd.new@@1M" -F -T 131072 -H 2048
|
||||||
|
if errorlevel 1 goto :CreateFailed
|
||||||
|
mformat -i "disk.vhd.new@@65M" -F -T 524288 -H 133120
|
||||||
|
if errorlevel 1 goto :CreateFailed
|
||||||
|
move /y "disk.vhd.new" "disk.vhd" >nul
|
||||||
|
if errorlevel 1 goto :CreateFailed
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:CreateFailed
|
||||||
|
if exist "disk.vhd.new" del /q "disk.vhd.new"
|
||||||
|
exit /b 1
|
||||||
+1
-3
@@ -8,7 +8,5 @@ system_volume = mbr/4E544C31/2
|
|||||||
; Debug bitmask. Values are defined canonically in ntlite/ddk/debug.h.
|
; Debug bitmask. Values are defined canonically in ntlite/ddk/debug.h.
|
||||||
; 0x001 console output, 0x002 explicit kernel diagnostics, 0x004 file log.
|
; 0x001 console output, 0x002 explicit kernel diagnostics, 0x004 file log.
|
||||||
; 0x008 pool canaries, 0x010 pool poison, 0x020 pool quarantine, 0x040 pool caller tracking.
|
; 0x008 pool canaries, 0x010 pool poison, 0x020 pool quarantine, 0x040 pool caller tracking.
|
||||||
; 0x080 display assertions, 0x100 intrusive-list checks.
|
; 0x080 display assertions, 0x100 intrusive-list checks, 0x200 ACPICA informational output.
|
||||||
debug = 0x004
|
debug = 0x004
|
||||||
[init]
|
|
||||||
commandline = apps/shell_native.exe
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DIRS=uefi
|
||||||
@@ -34,7 +34,6 @@ int _fltused = 0;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Implements the ascii Str To Unicode Str S operation.
|
|
||||||
static int AsciiStrToUnicodeStrS(const char* Source, CHAR16* Dest, size_t DestMax) {
|
static int AsciiStrToUnicodeStrS(const char* Source, CHAR16* Dest, size_t DestMax) {
|
||||||
if (!Source || !Dest || !DestMax) return -1;
|
if (!Source || !Dest || !DestMax) return -1;
|
||||||
|
|
||||||
@@ -46,7 +45,6 @@ static int AsciiStrToUnicodeStrS(const char* Source, CHAR16* Dest, size_t DestMa
|
|||||||
return -1; // Buffer too small
|
return -1; // Buffer too small
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ascii Str Cpy S operation.
|
|
||||||
static int AsciiStrCpyS(char* Dest, size_t DestMax, const char* Source) {
|
static int AsciiStrCpyS(char* Dest, size_t DestMax, const char* Source) {
|
||||||
if (!Dest || !Source || !DestMax) return -1;
|
if (!Dest || !Source || !DestMax) return -1;
|
||||||
|
|
||||||
@@ -79,7 +77,6 @@ static UINT64* AllocPage(EFI_PHYSICAL_ADDRESS* physOut) {
|
|||||||
|
|
||||||
static UINT64* gPml4;
|
static UINT64* gPml4;
|
||||||
|
|
||||||
// Implements the ensure Table operation.
|
|
||||||
static UINT64* EnsureTable(UINT64* parent, UINTN index) {
|
static UINT64* EnsureTable(UINT64* parent, UINTN index) {
|
||||||
if (!parent)
|
if (!parent)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
!include $(BASEDIR)\makefile.def
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
TARGETNAME=bootx64
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=PROGRAM
|
||||||
|
IMAGE_KIND=EFI
|
||||||
|
TARGETEXT=efi
|
||||||
|
FLAVOR=BOOT
|
||||||
|
EXTRA_CFLAGS=/I"$(BASEDIR)\code\boot\uefi\include"
|
||||||
|
TARGETLIBS="$(BASEDIR)\code\boot\uefi\efilib.lib" "$(BASEDIR)\bin\libc.lib"
|
||||||
|
EXTRA_LFLAGS=/FORCE:MULTIPLE /ENTRY:UefiMain
|
||||||
|
INCLUDES=$(BASEDIR)\code\boot\uefi\include
|
||||||
|
SOURCES=@/code/boot/uefi/boot_pe.c @/code/boot/uefi/main.c @/code/common/boot_volume_selector.c
|
||||||
@@ -1,715 +0,0 @@
|
|||||||
// Project build orchestrator. This file describes the Windows/MSVC build graph and keeps driver dependencies explicit.
|
|
||||||
|
|
||||||
#define NOB_IMPLEMENTATION
|
|
||||||
#include "nob.h"
|
|
||||||
|
|
||||||
// Compiler and linker flags stay in macros so they can be used in file-scope aggregate initializers.
|
|
||||||
// MSVC C rejects initializing a static object from another object, even when the source object is const.
|
|
||||||
// Drivers and user binaries do not inherit kernel include paths so private dependencies fail at compile time.
|
|
||||||
#define COMMON_CFLAGS_LITERAL "/nologo /W3 /WX /O2 /GS- /Gs999999 /Gz /Gy /EHsc- /GR- /Oi- /Z7 /std:c17 /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /Icode\\public /Icode\\common\\include"
|
|
||||||
#define KERNEL_CFLAGS_LITERAL COMMON_CFLAGS_LITERAL " /Icode\\kernel\\include"
|
|
||||||
#define DRIVER_CFLAGS_LITERAL COMMON_CFLAGS_LITERAL
|
|
||||||
#define USER_CFLAGS_LITERAL COMMON_CFLAGS_LITERAL
|
|
||||||
// POSIX targets own their standard C/POSIX headers; /X prevents the host UCRT from entering the target ABI.
|
|
||||||
#define POSIX_USER_CFLAGS_LITERAL "/X /Icode\\public\\posix /Icode\\public\\freestanding " USER_CFLAGS_LITERAL
|
|
||||||
#define BOOT_CFLAGS_LITERAL KERNEL_CFLAGS_LITERAL
|
|
||||||
#define USER_HEAP_OBJS_LITERAL "obj\\runtime\\user_heap.obj obj\\runtime\\user_heap_exports.obj"
|
|
||||||
#define NATIVE_RUNTIME_OBJS_LITERAL "obj\\runtime\\native_exception.obj obj\\runtime\\native_start.obj"
|
|
||||||
#define NATIVE_EXE_LIBS_LITERAL "bin\\syscall.lib obj\\libc.obj " USER_HEAP_OBJS_LITERAL " " NATIVE_RUNTIME_OBJS_LITERAL
|
|
||||||
#define NATIVE_INIT_LIBS_LITERAL "bin\\syscall_s.lib obj\\libc.obj obj\\runtime\\native_exception.obj"
|
|
||||||
#define NATIVE_SERVICE_LIBS_LITERAL "bin\\syscall_s.lib obj\\libc.obj " USER_HEAP_OBJS_LITERAL " obj\\runtime\\native_exception.obj"
|
|
||||||
#define WIN32_EXE_LIBS_LITERAL "bin\\win32.lib bin\\syscall.lib obj\\libc.obj obj\\runtime\\native_start.obj"
|
|
||||||
#define POSIX_EXE_LIBS_LITERAL "bin\\posix.lib bin\\syscall.lib obj\\libc.obj obj\\runtime\\posix_start.obj"
|
|
||||||
#define NATIVE_EXE_ENTRY_LITERAL "/ENTRY:NtlNativeStart"
|
|
||||||
#define USER_IMAGE_FLAGS_LITERAL "/DYNAMICBASE /HIGHENTROPYVA"
|
|
||||||
#define LWIP_CFLAGS_LITERAL DRIVER_CFLAGS_LITERAL " /Icode\\drivers\\net\\lwip\\include /Icode\\drivers\\net\\lwip\\third_party\\lwip\\src\\include /wd4005 /wd4100 /wd4103 /wd4127 /wd4244 /wd4267 /wd4706"
|
|
||||||
#define EXT4_CFLAGS_LITERAL DRIVER_CFLAGS_LITERAL " /Icode\\drivers\\fs\\ext4\\include /Icode\\drivers\\fs\\ext4\\third_party\\lwext4\\include /DCONFIG_USE_DEFAULT_CFG=1 /DCONFIG_HAVE_OWN_ERRNO=1 /DCONFIG_DEBUG_PRINTF=0 /DCONFIG_DEBUG_ASSERT=0 /DCONFIG_BLOCK_DEV_ENABLE_STATS=0 /DCONFIG_EXT4_BLOCKDEVS_COUNT=8 /DCONFIG_EXT4_MOUNTPOINTS_COUNT=8 /wd4005 /wd4100 /wd4101 /wd4103 /wd4127 /wd4244 /wd4267 /wd4706 /wd4996"
|
|
||||||
#define NTFS3G_CFLAGS_LITERAL DRIVER_CFLAGS_LITERAL " /Icode\\drivers\\fs\\ntfs\\ntfs3g\\include /Icode\\drivers\\fs\\ntfs\\ntfs3g\\third_party\\ntfs-3g\\include /Icode\\drivers\\fs\\ntfs\\ntfs3g\\third_party\\ntfs-3g\\include\\ntfs-3g /DHAVE_CONFIG_H=1 /DNO_NTFS_DEVICE_DEFAULT_IO_OPS=1 /wd4005 /wd4018 /wd4100 /wd4101 /wd4103 /wd4127 /wd4133 /wd4146 /wd4244 /wd4267 /wd4305 /wd4311 /wd4312 /wd4706 /wd4996"
|
|
||||||
#define LFLAGS_LITERAL "/nologo /NODEFAULTLIB /DEBUG"
|
|
||||||
|
|
||||||
// Partition offsets inside disk.vhd
|
|
||||||
#define VHD_PART1 "disk.vhd@@1M" // ESP / Partition 1 (Offset 1MB)
|
|
||||||
#define VHD_PART2 "disk.vhd@@65M" // Test/Data / Partition 2 (Offset 65MB)
|
|
||||||
#define DEFAULT_VHD_DISK_SIGNATURE 0x4E544C31u
|
|
||||||
|
|
||||||
const char* CommonCflags = COMMON_CFLAGS_LITERAL;
|
|
||||||
const char* KernelCflags = KERNEL_CFLAGS_LITERAL;
|
|
||||||
const char* UserCflags = USER_CFLAGS_LITERAL;
|
|
||||||
const char* PosixUserCflags = POSIX_USER_CFLAGS_LITERAL;
|
|
||||||
const char* BootCflags = BOOT_CFLAGS_LITERAL;
|
|
||||||
const char* LwipCflags = LWIP_CFLAGS_LITERAL;
|
|
||||||
const char* Ext4Cflags = EXT4_CFLAGS_LITERAL;
|
|
||||||
const char* Ntfs3gCflags = NTFS3G_CFLAGS_LITERAL;
|
|
||||||
const char* LFLAGS = LFLAGS_LITERAL;
|
|
||||||
|
|
||||||
typedef struct Driver_Target {
|
|
||||||
const char* name;
|
|
||||||
const char* obj_dir;
|
|
||||||
const char* sources;
|
|
||||||
const char* cflags;
|
|
||||||
const char* libs;
|
|
||||||
const char* entry_flag;
|
|
||||||
} Driver_Target;
|
|
||||||
|
|
||||||
#define DRIVER_TARGET(name_, obj_dir_, sources_) { (name_), (obj_dir_), (sources_), DRIVER_CFLAGS_LITERAL, "", "/NOENTRY" }
|
|
||||||
#define DRIVER_TARGET_LIBS(name_, obj_dir_, sources_, libs_) { (name_), (obj_dir_), (sources_), DRIVER_CFLAGS_LITERAL, (libs_), "/NOENTRY" }
|
|
||||||
#define DRIVER_TARGET_FLAGS(name_, obj_dir_, sources_, cflags_) { (name_), (obj_dir_), (sources_), (cflags_), "", "/NOENTRY" }
|
|
||||||
#define DRIVER_TARGET_DECLARATIVE(name_, obj_dir_, sources_) { (name_), (obj_dir_), (sources_), DRIVER_CFLAGS_LITERAL, "", "/NOENTRY" }
|
|
||||||
|
|
||||||
static const Driver_Target PCI_BUS_DRIVER =
|
|
||||||
DRIVER_TARGET_FLAGS("pci", "obj\\drivers\\pci", "code\\drivers\\bus\\pci\\pci.c", DRIVER_CFLAGS_LITERAL " /DPCI_SYS_BUILD");
|
|
||||||
|
|
||||||
static const Driver_Target STANDALONE_DRIVERS[] = {
|
|
||||||
DRIVER_TARGET("ps2", "obj\\drivers\\ps2", "code\\drivers\\input\\ps2\\ps2.c code\\drivers\\input\\ps2\\ps2_i8042.c"),
|
|
||||||
DRIVER_TARGET_DECLARATIVE("serial", "obj\\drivers\\serial", "code\\drivers\\input\\serial\\serial.c"),
|
|
||||||
DRIVER_TARGET_LIBS("hda", "obj\\drivers\\hda", "code\\drivers\\audio\\hda\\hda.c code\\drivers\\audio\\hda\\hda_transport.c code\\drivers\\audio\\hda\\hda_codec.c", "bin\\pci.lib"),
|
|
||||||
DRIVER_TARGET_LIBS("ata", "obj\\drivers\\ata", "code\\drivers\\storage\\ata\\ata.c", "bin\\pci.lib"),
|
|
||||||
DRIVER_TARGET_LIBS("ahci", "obj\\drivers\\ahci", "code\\drivers\\storage\\ahci\\ahci.c code\\drivers\\storage\\ahci\\ahci_port.c", "bin\\pci.lib"),
|
|
||||||
DRIVER_TARGET("fat", "obj\\drivers\\fat", "code\\drivers\\fs\\fat\\fat.c code\\drivers\\fs\\fat\\fat_directory.c code\\drivers\\fs\\fat\\fat_file.c code\\drivers\\fs\\fat\\fat_async.c code\\drivers\\fs\\fat\\fat_driver.c code\\drivers\\fs\\fat\\fat_mount.c"),
|
|
||||||
DRIVER_TARGET_LIBS("vmwaresvga", "obj\\drivers\\vmwaresvga", "code\\drivers\\display\\vmwaresvga\\vmwaresvga.c", "bin\\pci.lib"),
|
|
||||||
DRIVER_TARGET_LIBS("usb", "obj\\drivers\\usb", "code\\drivers\\bus\\usb\\usb.c code\\drivers\\bus\\usb\\usb_bus.c code\\drivers\\bus\\usb\\usb_composite.c code\\drivers\\bus\\usb\\usb_core.c code\\drivers\\bus\\usb\\usb_xhci.c code\\drivers\\bus\\usb\\usb_hid.c code\\drivers\\bus\\usb\\usb_storage.c code\\drivers\\bus\\usb\\usb_hub.c", "bin\\pci.lib"),
|
|
||||||
DRIVER_TARGET_LIBS("rtl816x", "obj\\drivers\\rtl816x", "code\\drivers\\net\\rtl816x\\rtl816x.c", "bin\\pci.lib"),
|
|
||||||
DRIVER_TARGET_LIBS("rtl8139", "obj\\drivers\\rtl8139", "code\\drivers\\net\\rtl8139\\rtl8139.c", "bin\\pci.lib"),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Creates layout.
|
|
||||||
void create_layout() {
|
|
||||||
const char* dirs[] = {
|
|
||||||
"obj", "bin", "obj\\boot", "obj\\ddk", "obj\\kernel", "obj\\lwip", "obj\\ext4", "obj\\ntfs3g", "obj\\hal",
|
|
||||||
"obj\\syscall", "obj\\runtime", "obj\\win32", "obj\\posix", "obj\\drivers", "obj\\init", "obj\\rssrv", "obj\\posixsrv", "obj\\dwm",
|
|
||||||
"obj\\shell_win32", "obj\\shell_posix", "obj\\shell_native",
|
|
||||||
"obj\\async_apc", "obj\\async_cancel", "obj\\apc_return_smoke", "obj\\edit", "obj\\httpget",
|
|
||||||
"obj\\tcpserve", "obj\\udp", "obj\\resolve", "obj\\ping", "obj\\doom", "obj\\video", "obj\\memtop",
|
|
||||||
"obj\\file_stat_smoke", "obj\\handle_dup_smoke", "obj\\security_smoke", "obj\\port_ipc_smoke", "obj\\resource_service_smoke", "obj\\anonymous_queue_smoke", "obj\\input_service_smoke", "obj\\console_service_smoke", "obj\\desktop_smoke", "obj\\timer_smoke", "obj\\stats_abi_smoke", "obj\\realpath_smoke", "obj\\file_lock_smoke", "obj\\process_protection_smoke", "obj\\process_exit_multithread_smoke", "obj\\thread_name_smoke", "obj\\process_builder_smoke", "obj\\socket_addr_smoke", "obj\\syscall_contract_smoke", "obj\\would_block_smoke", "obj\\audio_stream_smoke", "obj\\winmm_waveout_smoke", "obj\\win32_condition_variable_smoke", "obj\\win32_mutex_smoke", "obj\\win32_thread_suspend_smoke", "obj\\win32_module_lookup_smoke", "obj\\cwd_userspace_smoke", "obj\\mmap_smoke", "obj\\pcache_smoke", "obj\\pcache_pressure", "obj\\dirty_writeback", "obj\\shared_mmap",
|
|
||||||
"obj\\pcache_invalidate", "obj\\pcache_mmap_read_reuse", "obj\\pcache_multithread",
|
|
||||||
"obj\\all_tests", "obj\\posix_service_smoke", "obj\\surface_smoke", "obj\\surface_invalid_rect", "obj\\surface_multithread_commit", "obj\\surface_cross_process_smoke", "obj\\net_irp_smoke", "obj\\module_load_smoke", "obj\\posix_module_smoke", "obj\\posix_runtime_smoke", "obj\\posix_fd_smoke", "obj\\posix_process_smoke", "obj\\posix_signal_smoke", "obj\\posix_pipe_smoke", "obj\\exception_dispatcher_smoke", "obj\\native_exception_runtime_smoke", "obj\\native_raise_exception_smoke", "obj\\exception_smoke", "obj\\win32_exception_smoke", "obj\\win32_seh_smoke"
|
|
||||||
};
|
|
||||||
for (size_t i = 0; i < NOB_ARRAY_LEN(dirs); i++) nob_mkdir_if_not_exists(dirs[i]);
|
|
||||||
nob_mkdir_if_not_exists(PCI_BUS_DRIVER.obj_dir);
|
|
||||||
for (size_t i = 0; i < NOB_ARRAY_LEN(STANDALONE_DRIVERS); i++) nob_mkdir_if_not_exists(STANDALONE_DRIVERS[i].obj_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Runs a shell command and waits for it to finish.
|
|
||||||
bool run_sync(const char* cmd_str) {
|
|
||||||
Nob_Cmd cmd = {0};
|
|
||||||
nob_cmd_append(&cmd, "cmd.exe", "/c", cmd_str);
|
|
||||||
bool ok = nob_cmd_run_sync(cmd);
|
|
||||||
nob_cmd_free(cmd);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Launches a shell command while the build graph continues.
|
|
||||||
Nob_Proc run_async(const char* cmd_str) {
|
|
||||||
Nob_Cmd cmd = {0};
|
|
||||||
nob_cmd_append(&cmd, "cmd.exe", "/c", cmd_str);
|
|
||||||
Nob_Proc proc = nob_cmd_run_async(cmd);
|
|
||||||
nob_cmd_free(cmd);
|
|
||||||
return proc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deletes stale object files from a target directory before compiling into it.
|
|
||||||
bool clean_object_directory(const char* obj_dir) {
|
|
||||||
const char* cmd = nob_temp_sprintf("if exist %s\\*.obj del /q %s\\*.obj", obj_dir, obj_dir);
|
|
||||||
return run_sync(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleans object directories that are linked through wildcards.
|
|
||||||
bool clean_build_object_directories(void) {
|
|
||||||
const char* dirs[] = {
|
|
||||||
"obj\\boot", "obj\\ddk", "obj\\kernel", "obj\\lwip", "obj\\ext4", "obj\\hal",
|
|
||||||
"obj\\syscall", "obj\\runtime", "obj\\win32", "obj\\posix",
|
|
||||||
"obj\\init", "obj\\rssrv", "obj\\posixsrv", "obj\\dwm", "obj\\shell_win32", "obj\\shell_posix", "obj\\shell_native",
|
|
||||||
"obj\\async_apc", "obj\\async_cancel", "obj\\apc_return_smoke", "obj\\edit", "obj\\httpget",
|
|
||||||
"obj\\tcpserve", "obj\\udp", "obj\\resolve", "obj\\ping",
|
|
||||||
"obj\\doom", "obj\\video", "obj\\memtop", "obj\\file_stat_smoke", "obj\\handle_dup_smoke", "obj\\security_smoke", "obj\\port_ipc_smoke", "obj\\resource_service_smoke", "obj\\anonymous_queue_smoke", "obj\\input_service_smoke", "obj\\console_service_smoke", "obj\\desktop_smoke", "obj\\timer_smoke", "obj\\stats_abi_smoke", "obj\\realpath_smoke", "obj\\file_lock_smoke", "obj\\process_protection_smoke", "obj\\process_exit_multithread_smoke", "obj\\thread_name_smoke", "obj\\process_builder_smoke", "obj\\socket_addr_smoke", "obj\\syscall_contract_smoke", "obj\\would_block_smoke", "obj\\audio_stream_smoke", "obj\\winmm_waveout_smoke", "obj\\win32_condition_variable_smoke", "obj\\win32_mutex_smoke", "obj\\win32_thread_suspend_smoke", "obj\\win32_module_lookup_smoke", "obj\\cwd_userspace_smoke", "obj\\mmap_smoke", "obj\\pcache_smoke", "obj\\pcache_pressure", "obj\\dirty_writeback", "obj\\shared_mmap",
|
|
||||||
"obj\\pcache_invalidate", "obj\\pcache_mmap_read_reuse", "obj\\pcache_multithread",
|
|
||||||
"obj\\all_tests", "obj\\posix_service_smoke", "obj\\surface_smoke", "obj\\surface_invalid_rect", "obj\\surface_multithread_commit", "obj\\surface_cross_process_smoke", "obj\\net_irp_smoke", "obj\\module_load_smoke", "obj\\posix_module_smoke", "obj\\posix_runtime_smoke", "obj\\posix_fd_smoke", "obj\\posix_process_smoke", "obj\\posix_signal_smoke", "obj\\posix_pipe_smoke", "obj\\exception_dispatcher_smoke", "obj\\native_exception_runtime_smoke", "obj\\native_raise_exception_smoke", "obj\\exception_smoke", "obj\\win32_exception_smoke", "obj\\win32_seh_smoke"
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < NOB_ARRAY_LEN(dirs); i++) {
|
|
||||||
if (!clean_object_directory(dirs[i])) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!clean_object_directory(PCI_BUS_DRIVER.obj_dir)) return false;
|
|
||||||
for (size_t i = 0; i < NOB_ARRAY_LEN(STANDALONE_DRIVERS); i++) {
|
|
||||||
if (!clean_object_directory(STANDALONE_DRIVERS[i].obj_dir)) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates the USB fat root once and leaves its contents alone between builds.
|
|
||||||
bool create_usbfatroot_if_missing(void) {
|
|
||||||
return nob_mkdir_if_not_exists("usbfatroot");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copies one local file into a FAT image using mcopy without admin rights.
|
|
||||||
bool mcopy_file(const char* src, const char* vhd_target, const char* dst_path) {
|
|
||||||
const char* cmd = nob_temp_sprintf("mcopy -o -i %s %s ::%s", vhd_target, src, dst_path);
|
|
||||||
return run_sync(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copies several same-name files into one FAT directory with a single mcopy process.
|
|
||||||
bool mcopy_files_to_dir(const char* vhd_target,
|
|
||||||
const char* dst_dir,
|
|
||||||
const char* const* sources,
|
|
||||||
size_t source_count) {
|
|
||||||
if (!vhd_target || !dst_dir || (!sources && source_count))
|
|
||||||
return false;
|
|
||||||
if (!source_count)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
Nob_String_Builder command = {0};
|
|
||||||
nob_sb_appendf(&command, "mcopy -o -i %s", vhd_target);
|
|
||||||
for (size_t i = 0; i < source_count; ++i)
|
|
||||||
nob_sb_appendf(&command, " %s", sources[i]);
|
|
||||||
nob_sb_appendf(&command, " ::%s", dst_dir);
|
|
||||||
nob_sb_append_null(&command);
|
|
||||||
|
|
||||||
bool ok = run_sync(command.items);
|
|
||||||
nob_sb_free(command);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility to create a directory in a FAT image using mmd.
|
|
||||||
bool mmd_dir(const char* vhd_target, const char* dir_path) {
|
|
||||||
const char* cmd = nob_temp_sprintf("mmd -i %s ::%s 2>nul", vhd_target, dir_path);
|
|
||||||
run_sync(cmd);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes a 512-byte Connectix VHD Fixed Disk Footer at the end of the file.
|
|
||||||
static void write_vpc_footer(FILE* f, uint64_t disk_size_bytes) {
|
|
||||||
uint8_t footer[512] = {0};
|
|
||||||
|
|
||||||
memcpy(&footer[0], "conectix", 8);
|
|
||||||
|
|
||||||
// Features: 0x00000002 (Big Endian)
|
|
||||||
footer[11] = 0x02;
|
|
||||||
|
|
||||||
// File Format Version: 0x00010000
|
|
||||||
footer[13] = 0x01;
|
|
||||||
|
|
||||||
// Data Offset: 0xFFFFFFFFFFFFFFFF (Fixed disk)
|
|
||||||
memset(&footer[16], 0xFF, 8);
|
|
||||||
|
|
||||||
// Creator Application: "qemu"
|
|
||||||
memcpy(&footer[28], "qemu", 4);
|
|
||||||
|
|
||||||
// Creator Version: 0x00020000
|
|
||||||
footer[33] = 0x02;
|
|
||||||
|
|
||||||
// Creator Host OS: "Wi2k"
|
|
||||||
memcpy(&footer[36], "Wi2k", 4);
|
|
||||||
|
|
||||||
// Original & Current Size (uint64_t Big Endian)
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
uint8_t b = (uint8_t)(disk_size_bytes >> ((7 - i) * 8));
|
|
||||||
footer[40 + i] = b;
|
|
||||||
footer[48 + i] = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Geometry for 512MB: 1024 Cylinders (0x0400), 16 Heads, 63 Sectors/Track
|
|
||||||
footer[56] = 0x04;
|
|
||||||
footer[57] = 0x00;
|
|
||||||
footer[58] = 16;
|
|
||||||
footer[59] = 63;
|
|
||||||
|
|
||||||
// Disk Type: 2 (Fixed Hard Disk)
|
|
||||||
footer[63] = 0x02;
|
|
||||||
|
|
||||||
// Unique ID GUID
|
|
||||||
static const uint8_t guid[16] = {
|
|
||||||
0xA1, 0xB2, 0xC3, 0xD4, 0xE5, 0xF6, 0x78, 0x90,
|
|
||||||
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0
|
|
||||||
};
|
|
||||||
memcpy(&footer[68], guid, 16);
|
|
||||||
|
|
||||||
// Checksum: 1's complement sum of all bytes in footer with checksum cleared
|
|
||||||
uint32_t sum = 0;
|
|
||||||
for (int i = 0; i < 512; i++) {
|
|
||||||
sum += footer[i];
|
|
||||||
}
|
|
||||||
uint32_t checksum = ~sum;
|
|
||||||
|
|
||||||
footer[64] = (uint8_t)(checksum >> 24);
|
|
||||||
footer[65] = (uint8_t)(checksum >> 16);
|
|
||||||
footer[66] = (uint8_t)(checksum >> 8);
|
|
||||||
footer[67] = (uint8_t)(checksum & 0xFF);
|
|
||||||
|
|
||||||
fseek(f, (long)disk_size_bytes, SEEK_SET);
|
|
||||||
fwrite(footer, 1, 512, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensures the managed development VHD carries the stable identity used by boot.ini.
|
|
||||||
static bool ensure_disk_vhd_signature(void) {
|
|
||||||
FILE* f = fopen("disk.vhd", "r+b");
|
|
||||||
if (!f) return false;
|
|
||||||
|
|
||||||
uint32_t signature = DEFAULT_VHD_DISK_SIGNATURE;
|
|
||||||
if (fseek(f, 440, SEEK_SET) != 0 ||
|
|
||||||
fwrite(&signature, sizeof(signature), 1, f) != 1) {
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a 512 MB partitioned disk.vhd image with a valid VPC footer.
|
|
||||||
bool create_disk_vhd_if_missing(void) {
|
|
||||||
if (nob_file_exists("disk.vhd")) return ensure_disk_vhd_signature();
|
|
||||||
|
|
||||||
nob_log(NOB_INFO, "disk.vhd missing, creating new 512 MB fixed VHD image...");
|
|
||||||
|
|
||||||
const uint64_t disk_size = (uint64_t)512 * 1024 * 1024; // 512 MB Payload
|
|
||||||
FILE* f = fopen("disk.vhd", "wb");
|
|
||||||
if (!f) {
|
|
||||||
nob_log(NOB_ERROR, "Failed to create disk.vhd file!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expand file to 512MB payload
|
|
||||||
if (fseek(f, (long)(disk_size - 1), SEEK_SET) != 0) {
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
fputc(0, f);
|
|
||||||
|
|
||||||
// Build standard MBR partition table (Sector 0)
|
|
||||||
uint8_t mbr[512] = {0};
|
|
||||||
uint32_t disk_signature = DEFAULT_VHD_DISK_SIGNATURE;
|
|
||||||
memcpy(&mbr[440], &disk_signature, sizeof(disk_signature));
|
|
||||||
mbr[510] = 0x55;
|
|
||||||
mbr[511] = 0xAA;
|
|
||||||
|
|
||||||
// Partition 1 Entry: 64MB FAT32 @ LBA 2048 (1MB offset)
|
|
||||||
uint8_t* p1 = &mbr[0x01BE];
|
|
||||||
p1[0] = 0x80; // Active / Bootable
|
|
||||||
p1[1] = 0x00; p1[2] = 0x02; p1[3] = 0x00; // CHS Start
|
|
||||||
p1[4] = 0x0C; // FAT32 LBA
|
|
||||||
p1[5] = 0xFE; p1[6] = 0xFF; p1[7] = 0xFF; // CHS End (LBA boundary)
|
|
||||||
uint32_t p1_lba = 2048;
|
|
||||||
uint32_t p1_sectors = 131072; // 64 MB
|
|
||||||
memcpy(&p1[8], &p1_lba, 4);
|
|
||||||
memcpy(&p1[12], &p1_sectors, 4);
|
|
||||||
|
|
||||||
// Partition 2 Entry: 256MB FAT32 @ LBA 133120 (65MB offset)
|
|
||||||
uint8_t* p2 = &mbr[0x01CE];
|
|
||||||
p2[0] = 0x00; // Inactive
|
|
||||||
p2[1] = 0x00; p2[2] = 0x01; p2[3] = 0x08; // CHS Start
|
|
||||||
p2[4] = 0x0C; // FAT32 LBA
|
|
||||||
p2[5] = 0xFE; p2[6] = 0xFF; p2[7] = 0xFF; // CHS End (LBA boundary)
|
|
||||||
uint32_t p2_lba = 133120;
|
|
||||||
uint32_t p2_sectors = 524288; // 256 MB
|
|
||||||
memcpy(&p2[8], &p2_lba, 4);
|
|
||||||
memcpy(&p2[12], &p2_sectors, 4);
|
|
||||||
|
|
||||||
// Write Sector 0
|
|
||||||
fseek(f, 0, SEEK_SET);
|
|
||||||
fwrite(mbr, 1, 512, f);
|
|
||||||
|
|
||||||
// Append 512-byte Connectix VPC Footer
|
|
||||||
write_vpc_footer(f, disk_size);
|
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
nob_log(NOB_INFO, "Formatting disk.vhd partitions with mformat...");
|
|
||||||
if (!run_sync("mformat -i " VHD_PART1 " -F")) return false;
|
|
||||||
if (!run_sync("mformat -i " VHD_PART2 " -F")) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Runs the requested operation.
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
NOB_GO_REBUILD_URSELF(argc, argv);
|
|
||||||
bool with_tests = argc == 2 && strcmp(argv[1], "--with-tests") == 0;
|
|
||||||
if (argc != 1 && !with_tests) {
|
|
||||||
nob_log(NOB_ERROR, "Usage: build.exe [--with-tests]");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!create_disk_vhd_if_missing()) return 1;
|
|
||||||
if (!create_usbfatroot_if_missing()) return 1;
|
|
||||||
create_layout();
|
|
||||||
if (!nob_file_exists("code\\drivers\\fs\\ext4\\third_party\\lwext4\\src\\ext4.c")) {
|
|
||||||
nob_log(NOB_ERROR, "lwext4 is not vendored. Run: powershell -ExecutionPolicy Bypass -File code\\drivers\\fs\\ext4\\vendor_lwext4.ps1");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (!nob_file_exists("code\\drivers\\fs\\ntfs\\ntfs3g\\third_party\\ntfs-3g\\libntfs-3g\\volume.c")) {
|
|
||||||
nob_log(NOB_ERROR, "ntfs-3g is not vendored. Run: powershell -ExecutionPolicy Bypass -File code\\drivers\\fs\\ntfs\\ntfs3g\\vendor_ntfs3g.ps1");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (!clean_build_object_directories()) return 1;
|
|
||||||
|
|
||||||
nob_log(NOB_INFO, "--- Building Core Subsystems ---");
|
|
||||||
|
|
||||||
const char* core_tasks[] = {
|
|
||||||
"ml64 /nologo /c /Foobj\\kernel\\ke_switch.obj code\\kernel\\ke_switch.asm",
|
|
||||||
"ml64 /nologo /c /Foobj\\kernel\\ke_syscall_asm.obj code\\kernel\\ke_syscall.asm",
|
|
||||||
"ml64 /nologo /c /Foobj\\kernel\\ke_gdt_reload.obj code\\kernel\\ke_gdt_reload.asm",
|
|
||||||
"ml64 /nologo /c /Foobj\\syscall\\stubs.obj code\\user\\syscall\\syscall_stubs.asm",
|
|
||||||
"ml64 /nologo /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\stubs_s.obj code\\user\\syscall\\syscall_stubs.asm",
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\pe_loader.obj code\\user\\syscall\\pe_loader.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\pe_loader_s.obj code\\user\\syscall\\pe_loader.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\module_loader.obj code\\user\\syscall\\module_loader.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\module_loader_s.obj code\\user\\syscall\\module_loader.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\process_loader.obj code\\user\\syscall\\process_loader.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\process_loader_s.obj code\\user\\syscall\\process_loader.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\resource.obj code\\user\\syscall\\resource.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\resource_s.obj code\\user\\syscall\\resource.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\input_service.obj code\\user\\syscall\\input_service.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\input_service_s.obj code\\user\\syscall\\input_service.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\console_service.obj code\\user\\syscall\\console_service.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\console_service_s.obj code\\user\\syscall\\console_service.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\desktop.obj code\\user\\syscall\\desktop.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\desktop_s.obj code\\user\\syscall\\desktop.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\path.obj code\\user\\syscall\\path.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\path_s.obj code\\user\\syscall\\path.c", UserCflags),
|
|
||||||
"for %f in (code\\boot\\uefi\\*.asm) do ml64 /nologo /c /Fo\"obj\\boot\\%~nf.obj\" \"%f\"",
|
|
||||||
|
|
||||||
nob_temp_sprintf("cl %s /MP /c /Foobj\\ code\\common\\printf.c", CommonCflags),
|
|
||||||
"cl /nologo /c /Foobj\\libc.obj code\\common\\libc.c",
|
|
||||||
nob_temp_sprintf("cl %s /c /Foobj\\runtime\\user_heap.obj code\\user\\runtime\\heap.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /c /Foobj\\runtime\\user_heap_exports.obj code\\user\\runtime\\heap_exports.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /c /Foobj\\runtime\\native_exception.obj code\\user\\runtime\\native_exception.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /c /Foobj\\runtime\\native_start.obj code\\user\\runtime\\native_start.c", UserCflags),
|
|
||||||
nob_temp_sprintf("cl %s /c /Foobj\\runtime\\posix_start.obj code\\user\\runtime\\posix_start.c", PosixUserCflags),
|
|
||||||
|
|
||||||
// Bootloader.
|
|
||||||
nob_temp_sprintf("cl %s /MP /c /Icode\\boot\\uefi\\include /Foobj\\boot\\ code\\boot\\uefi\\*.c code\\common\\boot_volume_selector.c && link %s /FORCE:MULTIPLE /SUBSYSTEM:EFI_APPLICATION /ENTRY:UefiMain /OUT:bin\\bootx64.efi obj\\libc.obj code\\boot\\uefi\\efilib.lib obj\\boot\\*.obj", BootCflags, LFLAGS),
|
|
||||||
|
|
||||||
// HAL.
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_HAL_BUILD /MP /c /Foobj\\hal\\ code\\kernel\\hal\\*.c && link %s /DLL /FIXED /DYNAMICBASE:NO /HIGHENTROPYVA:NO /RELEASE /BASE:0xFFFF800010000000 /OUT:bin\\hal.dll /NOENTRY /IGNORE:4216 obj\\printf.obj obj\\libc.obj obj\\hal\\*.obj", KernelCflags, LFLAGS),
|
|
||||||
|
|
||||||
// Kernel.
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_KERNEL_BUILD /DKE_DISPLAY_BUILD /MP /c /Foobj\\kernel\\ code\\kernel\\*.c code\\common\\boot_volume_selector.c && link %s /SUBSYSTEM:NATIVE /FIXED /DYNAMICBASE:NO /HIGHENTROPYVA:NO /RELEASE /BASE:0xFFFF800000000000 /ENTRY:KernelMain /MAP:bin\\kernel.map /OUT:bin\\kernel.exe bin\\hal.lib obj\\printf.obj obj\\libc.obj obj\\kernel\\*.obj", KernelCflags, LFLAGS),
|
|
||||||
|
|
||||||
// Subsystem DLLs.
|
|
||||||
"link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL " USER_IMAGE_FLAGS_LITERAL " /OUT:bin\\syscall.dll obj\\syscall\\stubs.obj obj\\syscall\\pe_loader.obj obj\\syscall\\module_loader.obj obj\\syscall\\process_loader.obj obj\\syscall\\resource.obj obj\\syscall\\input_service.obj obj\\syscall\\console_service.obj obj\\syscall\\desktop.obj obj\\syscall\\path.obj obj\\libc.obj",
|
|
||||||
"lib /nologo /OUT:bin\\syscall_s.lib obj\\syscall\\stubs_s.obj obj\\syscall\\pe_loader_s.obj obj\\syscall\\module_loader_s.obj obj\\syscall\\process_loader_s.obj obj\\syscall\\resource_s.obj obj\\syscall\\input_service_s.obj obj\\syscall\\console_service_s.obj obj\\syscall\\desktop_s.obj obj\\syscall\\path_s.obj",
|
|
||||||
nob_temp_sprintf("cl %s /DUSER_HEAP_EXPORTS /DNTL_EXCEPTION_EXPORTS /MP /c /Foobj\\win32\\ code\\user\\runtime\\heap.c code\\user\\runtime\\heap_exports.c code\\user\\runtime\\native_exception.c code\\user\\personalities\\win32\\*.c && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL " USER_IMAGE_FLAGS_LITERAL " /OUT:bin\\win32.dll bin\\syscall.lib obj\\libc.obj obj\\win32\\*.obj", UserCflags),
|
|
||||||
"ml64 /nologo /Icode\\user\\syscall /c /Foobj\\posix\\posix_vfork_asm.obj code\\user\\personalities\\posix\\posix_vfork.asm",
|
|
||||||
nob_temp_sprintf("cl %s /DNTL_POSIX_BUILD /DUSER_HEAP_EXPORTS /DNTL_EXCEPTION_EXPORTS /MP /c /Foobj\\posix\\ code\\user\\runtime\\heap.c code\\user\\runtime\\heap_exports.c code\\user\\runtime\\native_exception.c code\\user\\personalities\\posix\\*.c && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL " USER_IMAGE_FLAGS_LITERAL " /OUT:bin\\posix.dll bin\\syscall.lib obj\\libc.obj obj\\posix\\*.obj", PosixUserCflags)
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < NOB_ARRAY_LEN(core_tasks); i++) {
|
|
||||||
if (!run_sync(core_tasks[i])) return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The support library contains only driver-side helpers, never kernel policy.
|
|
||||||
if (!run_sync(nob_temp_sprintf(
|
|
||||||
"cl %s /MP /c /Foobj\\ddk\\ code\\ddk\\*.c && lib /nologo /OUT:bin\\ntlddk.lib obj\\ddk\\*.obj",
|
|
||||||
DRIVER_CFLAGS_LITERAL))) return 1;
|
|
||||||
|
|
||||||
nob_log(NOB_INFO, "--- Building Bus Drivers ---");
|
|
||||||
const char* pci_cmd = nob_temp_sprintf(
|
|
||||||
"cl %s /MP /c /Fo%s\\ %s && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\%s.sys /IMPLIB:bin\\%s.lib /NOENTRY bin\\kernel.lib bin\\ntlddk.lib obj\\printf.obj obj\\libc.obj %s\\*.obj",
|
|
||||||
PCI_BUS_DRIVER.cflags, PCI_BUS_DRIVER.obj_dir, PCI_BUS_DRIVER.sources,
|
|
||||||
PCI_BUS_DRIVER.name, PCI_BUS_DRIVER.name, PCI_BUS_DRIVER.obj_dir
|
|
||||||
);
|
|
||||||
if (!run_sync(pci_cmd)) return 1;
|
|
||||||
|
|
||||||
nob_log(NOB_INFO, "--- Compiling Drivers and Apps in Parallel ---");
|
|
||||||
Nob_Procs procs = {0};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < NOB_ARRAY_LEN(STANDALONE_DRIVERS); i++) {
|
|
||||||
const Driver_Target* driver = &STANDALONE_DRIVERS[i];
|
|
||||||
const char* cmd = nob_temp_sprintf(
|
|
||||||
"cl %s /MP /c /Fo%s\\ %s && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\%s.sys %s bin\\kernel.lib %s obj\\libc.obj %s\\*.obj",
|
|
||||||
driver->cflags, driver->obj_dir, driver->sources, driver->name,
|
|
||||||
driver->entry_flag, driver->libs ? driver->libs : "", driver->obj_dir
|
|
||||||
);
|
|
||||||
nob_da_append(&procs, run_async(cmd));
|
|
||||||
}
|
|
||||||
|
|
||||||
Nob_String_Builder sb = {0}, lwip_files = {0};
|
|
||||||
if (nob_read_entire_file("code\\drivers\\net\\lwip\\lwip_sources.txt", &sb)) {
|
|
||||||
Nob_String_View sv = nob_sv_from_parts(sb.items, sb.count);
|
|
||||||
while (sv.count > 0) {
|
|
||||||
Nob_String_View line = nob_sv_trim(nob_sv_chop_by_delim(&sv, '\n'));
|
|
||||||
if (line.count > 0 && line.data[0] != '#') {
|
|
||||||
nob_sb_append_cstr(&lwip_files, "code\\");
|
|
||||||
for (size_t i = 0; i < line.count; i++) nob_sb_append_buf(&lwip_files, &(char){line.data[i] == '/' ? '\\' : line.data[i]}, 1);
|
|
||||||
nob_sb_append_cstr(&lwip_files, " ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nob_sb_append_null(&lwip_files);
|
|
||||||
nob_da_append(&procs, run_async(nob_temp_sprintf("cl %s /MP /c /Foobj\\lwip\\ %s && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\lwip.sys /NOENTRY bin\\kernel.lib obj\\libc.obj obj\\lwip\\*.obj", LwipCflags, lwip_files.items)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Nob_String_Builder ext4_sb = {0}, ext4_files = {0};
|
|
||||||
if (nob_read_entire_file("code\\drivers\\fs\\ext4\\lwext4_sources.txt", &ext4_sb)) {
|
|
||||||
Nob_String_View sv = nob_sv_from_parts(ext4_sb.items, ext4_sb.count);
|
|
||||||
while (sv.count > 0) {
|
|
||||||
Nob_String_View line = nob_sv_trim(nob_sv_chop_by_delim(&sv, '\n'));
|
|
||||||
if (line.count > 0 && line.data[0] != '#') {
|
|
||||||
nob_sb_append_cstr(&ext4_files, "code\\");
|
|
||||||
for (size_t i = 0; i < line.count; i++) nob_sb_append_buf(&ext4_files, &(char){line.data[i] == '/' ? '\\' : line.data[i]}, 1);
|
|
||||||
nob_sb_append_cstr(&ext4_files, " ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nob_sb_append_null(&ext4_files);
|
|
||||||
nob_da_append(&procs, run_async(nob_temp_sprintf("cl %s /MP /c /Foobj\\ext4\\ %s && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\ext4.sys /NOENTRY bin\\kernel.lib obj\\libc.obj obj\\ext4\\*.obj", Ext4Cflags, ext4_files.items)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Nob_String_Builder ntfs3g_sb = {0}, ntfs3g_files = {0};
|
|
||||||
if (nob_read_entire_file("code\\drivers\\fs\\ntfs\\ntfs3g\\ntfs3g_sources.txt", &ntfs3g_sb)) {
|
|
||||||
Nob_String_View sv = nob_sv_from_parts(ntfs3g_sb.items, ntfs3g_sb.count);
|
|
||||||
while (sv.count > 0) {
|
|
||||||
Nob_String_View line = nob_sv_trim(nob_sv_chop_by_delim(&sv, '\n'));
|
|
||||||
if (line.count > 0 && line.data[0] != '#') {
|
|
||||||
nob_sb_append_cstr(&ntfs3g_files, "code\\");
|
|
||||||
for (size_t i = 0; i < line.count; i++) nob_sb_append_buf(&ntfs3g_files, &(char){line.data[i] == '/' ? '\\' : line.data[i]}, 1);
|
|
||||||
nob_sb_append_cstr(&ntfs3g_files, " ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nob_sb_append_null(&ntfs3g_files);
|
|
||||||
nob_da_append(&procs, run_async(nob_temp_sprintf("cl %s /MP /c /Foobj\\ntfs3g\\ %s && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\ntfs.sys /NOENTRY bin\\kernel.lib obj\\printf.obj obj\\libc.obj obj\\ntfs3g\\*.obj", Ntfs3gCflags, ntfs3g_files.items)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char* apps[][4] = {
|
|
||||||
{"system\\init", NATIVE_INIT_LIBS_LITERAL, "init", "/ENTRY:_start"},
|
|
||||||
{"system\\rssrv", NATIVE_SERVICE_LIBS_LITERAL, "rssrv", "/ENTRY:_start"},
|
|
||||||
{"system\\posixsrv", NATIVE_SERVICE_LIBS_LITERAL, "posixsrv", "/ENTRY:_start"},
|
|
||||||
{"system\\dwm", NATIVE_SERVICE_LIBS_LITERAL, "dwm", "/ENTRY:_start"},
|
|
||||||
{"tests\\all_tests", NATIVE_EXE_LIBS_LITERAL, "all_tests", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\posix_service_smoke", NATIVE_EXE_LIBS_LITERAL, "posix_service_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"apps\\shell_win32", WIN32_EXE_LIBS_LITERAL, "shell_win32", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"apps\\shell_posix", POSIX_EXE_LIBS_LITERAL, "shell_posix", "/ENTRY:PosixStart"},
|
|
||||||
{"apps\\shell_native", NATIVE_EXE_LIBS_LITERAL, "shell_native", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\async_apc", NATIVE_EXE_LIBS_LITERAL, "async_apc", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\apc_return_smoke", NATIVE_EXE_LIBS_LITERAL, "apc_return_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\async_cancel", NATIVE_EXE_LIBS_LITERAL, "async_cancel", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\file_stat_smoke", NATIVE_EXE_LIBS_LITERAL, "file_stat_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\handle_dup_smoke", NATIVE_EXE_LIBS_LITERAL, "handle_dup_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\security_smoke", NATIVE_EXE_LIBS_LITERAL, "security_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\port_ipc_smoke", NATIVE_EXE_LIBS_LITERAL, "port_ipc_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\resource_service_smoke", NATIVE_EXE_LIBS_LITERAL, "resource_service_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\anonymous_queue_smoke", NATIVE_EXE_LIBS_LITERAL, "anonymous_queue_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\input_service_smoke", NATIVE_EXE_LIBS_LITERAL, "input_service_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\console_service_smoke", NATIVE_EXE_LIBS_LITERAL, "console_service_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\desktop_smoke", NATIVE_EXE_LIBS_LITERAL, "desktop_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\timer_smoke", NATIVE_EXE_LIBS_LITERAL, "timer_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\stats_abi_smoke", NATIVE_EXE_LIBS_LITERAL, "stats_abi_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\realpath_smoke", NATIVE_EXE_LIBS_LITERAL, "realpath_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\file_lock_smoke", NATIVE_EXE_LIBS_LITERAL, "file_lock_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\process_protection_smoke", NATIVE_EXE_LIBS_LITERAL, "process_protection_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\process_exit_multithread_smoke", NATIVE_EXE_LIBS_LITERAL, "process_exit_multithread_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\thread_name_smoke", NATIVE_EXE_LIBS_LITERAL, "thread_name_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\process_builder_smoke", "bin\\syscall_s.lib obj\\libc.obj " NATIVE_RUNTIME_OBJS_LITERAL, "process_builder_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\socket_addr_smoke", NATIVE_EXE_LIBS_LITERAL, "socket_addr_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\net_irp_smoke", NATIVE_EXE_LIBS_LITERAL, "net_irp_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\module_load_smoke", NATIVE_EXE_LIBS_LITERAL, "module_load_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\posix_module_smoke", POSIX_EXE_LIBS_LITERAL, "posix_module_smoke", "/ENTRY:PosixStart"},
|
|
||||||
{"tests\\posix_runtime_smoke", POSIX_EXE_LIBS_LITERAL, "posix_runtime_smoke", "/ENTRY:PosixStart"},
|
|
||||||
{"tests\\posix_fd_smoke", POSIX_EXE_LIBS_LITERAL, "posix_fd_smoke", "/ENTRY:PosixStart"},
|
|
||||||
{"tests\\posix_process_smoke", POSIX_EXE_LIBS_LITERAL, "posix_process_smoke", "/ENTRY:PosixStart"},
|
|
||||||
{"tests\\posix_signal_smoke", POSIX_EXE_LIBS_LITERAL, "posix_signal_smoke", "/ENTRY:PosixStart"},
|
|
||||||
{"tests\\posix_pipe_smoke", POSIX_EXE_LIBS_LITERAL, "posix_pipe_smoke", "/ENTRY:PosixStart"},
|
|
||||||
{"tests\\exception_dispatcher_smoke", NATIVE_EXE_LIBS_LITERAL, "exception_dispatcher_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\native_exception_runtime_smoke", NATIVE_EXE_LIBS_LITERAL, "native_exception_runtime_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\native_raise_exception_smoke", NATIVE_EXE_LIBS_LITERAL, "native_raise_exception_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\exception_smoke", NATIVE_EXE_LIBS_LITERAL, "exception_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\win32_exception_smoke", WIN32_EXE_LIBS_LITERAL, "win32_exception_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\win32_seh_smoke", WIN32_EXE_LIBS_LITERAL, "win32_seh_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\syscall_contract_smoke", NATIVE_EXE_LIBS_LITERAL, "syscall_contract_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\would_block_smoke", NATIVE_EXE_LIBS_LITERAL, "would_block_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\audio_stream_smoke", NATIVE_EXE_LIBS_LITERAL, "audio_stream_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\winmm_waveout_smoke", WIN32_EXE_LIBS_LITERAL, "winmm_waveout_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\win32_condition_variable_smoke", WIN32_EXE_LIBS_LITERAL, "win32_condition_variable_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\win32_mutex_smoke", WIN32_EXE_LIBS_LITERAL, "win32_mutex_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\win32_thread_suspend_smoke", WIN32_EXE_LIBS_LITERAL, "win32_thread_suspend_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\win32_module_lookup_smoke", WIN32_EXE_LIBS_LITERAL, "win32_module_lookup_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\cwd_userspace_smoke", NATIVE_EXE_LIBS_LITERAL, "cwd_userspace_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\mmap_smoke", NATIVE_EXE_LIBS_LITERAL, "mmap_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\pcache_smoke", NATIVE_EXE_LIBS_LITERAL, "pcache_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\pcache_pressure", NATIVE_EXE_LIBS_LITERAL, "pcache_pressure", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\dirty_writeback", NATIVE_EXE_LIBS_LITERAL, "dirty_writeback", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\shared_mmap", NATIVE_EXE_LIBS_LITERAL, "shared_mmap", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\pcache_invalidate", NATIVE_EXE_LIBS_LITERAL, "pcache_invalidate", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\pcache_mmap_read_reuse", NATIVE_EXE_LIBS_LITERAL, "pcache_mmap_read_reuse", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\pcache_multithread", NATIVE_EXE_LIBS_LITERAL, "pcache_multithread", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\surface_smoke", NATIVE_EXE_LIBS_LITERAL, "surface_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\surface_invalid_rect", NATIVE_EXE_LIBS_LITERAL, "surface_invalid_rect", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\surface_multithread_commit", NATIVE_EXE_LIBS_LITERAL, "surface_multithread_commit", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"tests\\surface_cross_process_smoke", NATIVE_EXE_LIBS_LITERAL, "surface_cross_process_smoke", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"apps\\edit", NATIVE_EXE_LIBS_LITERAL, "edit", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"apps\\httpget", NATIVE_EXE_LIBS_LITERAL, "httpget", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"apps\\tcpserve", NATIVE_EXE_LIBS_LITERAL, "tcpserve", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"apps\\udp", NATIVE_EXE_LIBS_LITERAL, "udp", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"apps\\resolve", NATIVE_EXE_LIBS_LITERAL, "resolve", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"apps\\ping", NATIVE_EXE_LIBS_LITERAL, "ping", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"apps\\doom", NATIVE_EXE_LIBS_LITERAL, "doom", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"apps\\video", "bin\\syscall.lib obj\\libc.obj " NATIVE_RUNTIME_OBJS_LITERAL " code\\user\\apps\\video\\bink2w64.lib", "video", NATIVE_EXE_ENTRY_LITERAL},
|
|
||||||
{"apps\\memtop", NATIVE_EXE_LIBS_LITERAL, "memtop", NATIVE_EXE_ENTRY_LITERAL}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < NOB_ARRAY_LEN(apps); i++) {
|
|
||||||
if (!with_tests && strncmp(apps[i][0], "tests\\", 6) == 0)
|
|
||||||
continue;
|
|
||||||
const char* appCflags = strcmp(apps[i][3], "/ENTRY:PosixStart") == 0
|
|
||||||
? PosixUserCflags
|
|
||||||
: UserCflags;
|
|
||||||
const char* cmd = nob_temp_sprintf(
|
|
||||||
"cl %s /MP /c /Foobj\\%s\\ code\\user\\%s\\*.c && link %s /SUBSYSTEM:NATIVE " USER_IMAGE_FLAGS_LITERAL " %s /OUT:bin\\%s.exe /PDB:bin\\%s.pdb %s obj\\%s\\*.obj",
|
|
||||||
appCflags, apps[i][2], apps[i][0], LFLAGS, apps[i][3], apps[i][2], apps[i][2], apps[i][1], apps[i][2]
|
|
||||||
);
|
|
||||||
nob_da_append(&procs, run_async(cmd));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nob_procs_wait(procs)) {
|
|
||||||
nob_log(NOB_ERROR, "One or more parallel build jobs failed!");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Formatting and Packing VHD via mtools (No Admin, Fast).
|
|
||||||
nob_log(NOB_INFO, "--- Formatting & Packing disk.vhd with mtools ---");
|
|
||||||
|
|
||||||
run_sync("mformat -i " VHD_PART1 " -F");
|
|
||||||
run_sync("mformat -i " VHD_PART2 " -F");
|
|
||||||
|
|
||||||
mmd_dir(VHD_PART1, "EFI");
|
|
||||||
mmd_dir(VHD_PART1, "EFI/BOOT");
|
|
||||||
mmd_dir(VHD_PART1, "EFI/NTLite");
|
|
||||||
mmd_dir(VHD_PART1, "EFI/NTLite/fs");
|
|
||||||
mmd_dir(VHD_PART2, "apps");
|
|
||||||
mmd_dir(VHD_PART2, "system");
|
|
||||||
mmd_dir(VHD_PART2, "drivers");
|
|
||||||
if (with_tests) mmd_dir(VHD_PART2, "tests");
|
|
||||||
|
|
||||||
// The ESP is only the boot anchor; the configured system volume carries the OS payload.
|
|
||||||
if (!mcopy_file("bin\\bootx64.efi", VHD_PART1, "EFI/BOOT/bootx64.efi")) return 1;
|
|
||||||
if (!mcopy_file("code\\boot.ini", VHD_PART1, "boot.ini")) return 1;
|
|
||||||
if (!run_sync("if exist code\\boot\\uefi\\fs\\*.efi mcopy -o -i " VHD_PART1 " code\\boot\\uefi\\fs\\*.efi ::EFI/NTLite/fs/")) return 1;
|
|
||||||
|
|
||||||
if (!mcopy_file("bin\\kernel.exe", VHD_PART2, "system/colonel.exe")) return 1;
|
|
||||||
|
|
||||||
const char* system_files[] = {
|
|
||||||
"bin\\hal.dll",
|
|
||||||
"bin\\syscall.dll",
|
|
||||||
"bin\\win32.dll",
|
|
||||||
"bin\\posix.dll",
|
|
||||||
"code\\settings.ini",
|
|
||||||
"code\\services.ini",
|
|
||||||
"bin\\init.exe",
|
|
||||||
"bin\\rssrv.exe",
|
|
||||||
"bin\\posixsrv.exe",
|
|
||||||
"bin\\dwm.exe",
|
|
||||||
};
|
|
||||||
if (!mcopy_files_to_dir(VHD_PART2, "system/", system_files, NOB_ARRAY_LEN(system_files))) return 1;
|
|
||||||
|
|
||||||
const char* driver_files[] = {
|
|
||||||
"bin\\pci.sys",
|
|
||||||
"bin\\ps2.sys",
|
|
||||||
"bin\\hda.sys",
|
|
||||||
"bin\\ata.sys",
|
|
||||||
"bin\\ahci.sys",
|
|
||||||
"bin\\fat.sys",
|
|
||||||
"bin\\ntfs.sys",
|
|
||||||
"bin\\ext4.sys",
|
|
||||||
"bin\\vmwaresvga.sys",
|
|
||||||
"bin\\lwip.sys",
|
|
||||||
"bin\\usb.sys",
|
|
||||||
"bin\\rtl816x.sys",
|
|
||||||
"bin\\rtl8139.sys",
|
|
||||||
"code\\drivers\\drivers.ini",
|
|
||||||
};
|
|
||||||
if (!mcopy_files_to_dir(VHD_PART2, "drivers/", driver_files, NOB_ARRAY_LEN(driver_files))) return 1;
|
|
||||||
// The build artifact keeps the descriptive target name; the installed serial driver gets the cereal joke.
|
|
||||||
if (!mcopy_file("bin\\serial.sys", VHD_PART2, "drivers/cereal.sys")) return 1;
|
|
||||||
|
|
||||||
const char* app_files[] = {
|
|
||||||
"bin\\shell_win32.exe",
|
|
||||||
"bin\\shell_posix.exe",
|
|
||||||
"bin\\shell_native.exe",
|
|
||||||
"bin\\edit.exe",
|
|
||||||
"bin\\httpget.exe",
|
|
||||||
"bin\\tcpserve.exe",
|
|
||||||
"bin\\udp.exe",
|
|
||||||
"bin\\resolve.exe",
|
|
||||||
"bin\\ping.exe",
|
|
||||||
"bin\\doom.exe",
|
|
||||||
"bin\\video.exe",
|
|
||||||
"bin\\memtop.exe",
|
|
||||||
};
|
|
||||||
if (!mcopy_files_to_dir(VHD_PART2, "apps/", app_files, NOB_ARRAY_LEN(app_files))) return 1;
|
|
||||||
|
|
||||||
const char* test_files[] = {
|
|
||||||
"bin\\all_tests.exe",
|
|
||||||
"bin\\posix_service_smoke.exe",
|
|
||||||
"bin\\async_apc.exe",
|
|
||||||
"bin\\async_cancel.exe",
|
|
||||||
"bin\\apc_return_smoke.exe",
|
|
||||||
"bin\\file_stat_smoke.exe",
|
|
||||||
"bin\\handle_dup_smoke.exe",
|
|
||||||
"bin\\security_smoke.exe",
|
|
||||||
"bin\\port_ipc_smoke.exe",
|
|
||||||
"bin\\resource_service_smoke.exe",
|
|
||||||
"bin\\anonymous_queue_smoke.exe",
|
|
||||||
"bin\\input_service_smoke.exe",
|
|
||||||
"bin\\console_service_smoke.exe",
|
|
||||||
"bin\\desktop_smoke.exe",
|
|
||||||
"bin\\timer_smoke.exe",
|
|
||||||
"bin\\stats_abi_smoke.exe",
|
|
||||||
"bin\\realpath_smoke.exe",
|
|
||||||
"bin\\file_lock_smoke.exe",
|
|
||||||
"bin\\process_protection_smoke.exe",
|
|
||||||
"bin\\process_exit_multithread_smoke.exe",
|
|
||||||
"bin\\thread_name_smoke.exe",
|
|
||||||
"bin\\process_builder_smoke.exe",
|
|
||||||
"bin\\socket_addr_smoke.exe",
|
|
||||||
"bin\\net_irp_smoke.exe",
|
|
||||||
"bin\\module_load_smoke.exe",
|
|
||||||
"bin\\posix_module_smoke.exe",
|
|
||||||
"bin\\posix_runtime_smoke.exe",
|
|
||||||
"bin\\posix_fd_smoke.exe",
|
|
||||||
"bin\\posix_process_smoke.exe",
|
|
||||||
"bin\\posix_signal_smoke.exe",
|
|
||||||
"bin\\posix_pipe_smoke.exe",
|
|
||||||
"bin\\exception_dispatcher_smoke.exe",
|
|
||||||
"bin\\native_exception_runtime_smoke.exe",
|
|
||||||
"bin\\native_raise_exception_smoke.exe",
|
|
||||||
"bin\\exception_smoke.exe",
|
|
||||||
"bin\\win32_exception_smoke.exe",
|
|
||||||
"bin\\win32_seh_smoke.exe",
|
|
||||||
"bin\\syscall_contract_smoke.exe",
|
|
||||||
"bin\\would_block_smoke.exe",
|
|
||||||
"bin\\audio_stream_smoke.exe",
|
|
||||||
"bin\\winmm_waveout_smoke.exe",
|
|
||||||
"bin\\win32_condition_variable_smoke.exe",
|
|
||||||
"bin\\win32_mutex_smoke.exe",
|
|
||||||
"bin\\win32_thread_suspend_smoke.exe",
|
|
||||||
"bin\\win32_module_lookup_smoke.exe",
|
|
||||||
"bin\\cwd_userspace_smoke.exe",
|
|
||||||
"bin\\mmap_smoke.exe",
|
|
||||||
"bin\\pcache_smoke.exe",
|
|
||||||
"bin\\pcache_pressure.exe",
|
|
||||||
"bin\\dirty_writeback.exe",
|
|
||||||
"bin\\shared_mmap.exe",
|
|
||||||
"bin\\pcache_invalidate.exe",
|
|
||||||
"bin\\pcache_mmap_read_reuse.exe",
|
|
||||||
"bin\\pcache_multithread.exe",
|
|
||||||
"bin\\surface_smoke.exe",
|
|
||||||
"bin\\surface_invalid_rect.exe",
|
|
||||||
"bin\\surface_multithread_commit.exe",
|
|
||||||
"bin\\surface_cross_process_smoke.exe",
|
|
||||||
};
|
|
||||||
if (with_tests && !mcopy_files_to_dir(VHD_PART2, "tests/", test_files, NOB_ARRAY_LEN(test_files))) return 1;
|
|
||||||
|
|
||||||
const char* optional_app_files[3];
|
|
||||||
size_t optional_app_count = 0;
|
|
||||||
if (nob_file_exists("code\\user\\apps\\video\\bink2w64.dll"))
|
|
||||||
optional_app_files[optional_app_count++] = "code\\user\\apps\\video\\bink2w64.dll";
|
|
||||||
if (nob_file_exists("code\\user\\apps\\video\\video.bk2"))
|
|
||||||
optional_app_files[optional_app_count++] = "code\\user\\apps\\video\\video.bk2";
|
|
||||||
if (nob_file_exists("code\\user\\apps\\doom\\doom1.wad"))
|
|
||||||
optional_app_files[optional_app_count++] = "code\\user\\apps\\doom\\doom1.wad";
|
|
||||||
if (!mcopy_files_to_dir(VHD_PART2, "apps/", optional_app_files, optional_app_count)) return 1;
|
|
||||||
|
|
||||||
nob_log(NOB_INFO, "Build complete!");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
-3286
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1 @@
|
|||||||
|
DIRS=libc printf
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
|
|
||||||
// Implements the strcpy operation.
|
|
||||||
char* strcpy(char* dest, const char* src) {
|
char* strcpy(char* dest, const char* src) {
|
||||||
char* d = dest;
|
char* d = dest;
|
||||||
while (*src) *d++ = *src++;
|
while (*src) *d++ = *src++;
|
||||||
@@ -12,7 +11,6 @@ char* strcpy(char* dest, const char* src) {
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the strncpy operation.
|
|
||||||
char* strncpy(char* dest, const char* src, size_t n) {
|
char* strncpy(char* dest, const char* src, size_t n) {
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < n && src[i]; i++) dest[i] = src[i];
|
for (i = 0; i < n && src[i]; i++) dest[i] = src[i];
|
||||||
@@ -45,7 +43,6 @@ char* strstr(const char* haystack, const char* needle) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the strcat operation.
|
|
||||||
char* strcat(char* dest, const char* src) {
|
char* strcat(char* dest, const char* src) {
|
||||||
char* ptr = dest;
|
char* ptr = dest;
|
||||||
while (*ptr != '\0') {
|
while (*ptr != '\0') {
|
||||||
@@ -60,7 +57,6 @@ char* strcat(char* dest, const char* src) {
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the strncat operation.
|
|
||||||
char* strncat(char* dest, const char* src, size_t n) {
|
char* strncat(char* dest, const char* src, size_t n) {
|
||||||
char* ptr = dest;
|
char* ptr = dest;
|
||||||
while (*ptr != '\0') {
|
while (*ptr != '\0') {
|
||||||
@@ -76,13 +72,11 @@ char* strncat(char* dest, const char* src, size_t n) {
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the strcmp operation.
|
|
||||||
int strcmp(const char* s1, const char* s2) {
|
int strcmp(const char* s1, const char* s2) {
|
||||||
while (*s1 && *s1 == *s2) s1++, s2++;
|
while (*s1 && *s1 == *s2) s1++, s2++;
|
||||||
return (unsigned char)*s1 - (unsigned char)*s2;
|
return (unsigned char)*s1 - (unsigned char)*s2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the strncmp operation.
|
|
||||||
int strncmp(const char* s1, const char* s2, size_t n) {
|
int strncmp(const char* s1, const char* s2, size_t n) {
|
||||||
while (n && *s1 && (*s1 == *s2)) {
|
while (n && *s1 && (*s1 == *s2)) {
|
||||||
s1++;
|
s1++;
|
||||||
@@ -92,7 +86,6 @@ int strncmp(const char* s1, const char* s2, size_t n) {
|
|||||||
return n == 0 ? 0 : *(unsigned char*)s1 - *(unsigned char*)s2;
|
return n == 0 ? 0 : *(unsigned char*)s1 - *(unsigned char*)s2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the stricmp operation.
|
|
||||||
int _stricmp(const char* s1, const char* s2) {
|
int _stricmp(const char* s1, const char* s2) {
|
||||||
// ASCII case folding works here because bit 0x20 distinguishes 'A' from 'a'.
|
// ASCII case folding works here because bit 0x20 distinguishes 'A' from 'a'.
|
||||||
while (*s1 && ((*s1 | 0x20) == (*s2 | 0x20))) {
|
while (*s1 && ((*s1 | 0x20) == (*s2 | 0x20))) {
|
||||||
@@ -101,14 +94,12 @@ int _stricmp(const char* s1, const char* s2) {
|
|||||||
return (unsigned char)(*s1 | 0x20) - (unsigned char)(*s2 | 0x20);
|
return (unsigned char)(*s1 | 0x20) - (unsigned char)(*s2 | 0x20);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the strlen operation.
|
|
||||||
size_t strlen(const char* s) {
|
size_t strlen(const char* s) {
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
while (*s++) n++;
|
while (*s++) n++;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the strnlen operation.
|
|
||||||
size_t strnlen(const char* s, size_t maxlen) {
|
size_t strnlen(const char* s, size_t maxlen) {
|
||||||
size_t len;
|
size_t len;
|
||||||
for (len = 0; len < maxlen; len++) {
|
for (len = 0; len < maxlen; len++) {
|
||||||
@@ -119,7 +110,6 @@ size_t strnlen(const char* s, size_t maxlen) {
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the strchr operation.
|
|
||||||
char* strchr(const char* s, int c) {
|
char* strchr(const char* s, int c) {
|
||||||
while (*s) {
|
while (*s) {
|
||||||
if (*s == (char)c) return (char*)s;
|
if (*s == (char)c) return (char*)s;
|
||||||
@@ -128,7 +118,6 @@ char* strchr(const char* s, int c) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the strrchr operation.
|
|
||||||
char* strrchr(const char* s, int c) {
|
char* strrchr(const char* s, int c) {
|
||||||
char ch = (char)c;
|
char ch = (char)c;
|
||||||
const char* last = NULL;
|
const char* last = NULL;
|
||||||
@@ -150,7 +139,6 @@ void *memchr(const void *s, int c, size_t n) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the memset operation.
|
|
||||||
void* memset(void* dest, int c, size_t n) {
|
void* memset(void* dest, int c, size_t n) {
|
||||||
unsigned char* d = (unsigned char*)dest;
|
unsigned char* d = (unsigned char*)dest;
|
||||||
size_t qwords = n / 8;
|
size_t qwords = n / 8;
|
||||||
@@ -172,7 +160,6 @@ void* memset(void* dest, int c, size_t n) {
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the memcpy operation.
|
|
||||||
void* memcpy(void* dest, const void* src, size_t n) {
|
void* memcpy(void* dest, const void* src, size_t n) {
|
||||||
unsigned char* d = (unsigned char*)dest;
|
unsigned char* d = (unsigned char*)dest;
|
||||||
const unsigned char* s = (const unsigned char*)src;
|
const unsigned char* s = (const unsigned char*)src;
|
||||||
@@ -192,7 +179,6 @@ void* memcpy(void* dest, const void* src, size_t n) {
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the memmove operation.
|
|
||||||
void* memmove(void* dest, const void* src, size_t n) {
|
void* memmove(void* dest, const void* src, size_t n) {
|
||||||
unsigned char* d = (unsigned char*)dest;
|
unsigned char* d = (unsigned char*)dest;
|
||||||
const unsigned char* s = (const unsigned char*)src;
|
const unsigned char* s = (const unsigned char*)src;
|
||||||
@@ -233,7 +219,6 @@ void* memmove(void* dest, const void* src, size_t n) {
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the memcmp operation.
|
|
||||||
int memcmp(const void* s1, const void* s2, size_t n) {
|
int memcmp(const void* s1, const void* s2, size_t n) {
|
||||||
const unsigned __int64* a64 = (const unsigned __int64*)s1;
|
const unsigned __int64* a64 = (const unsigned __int64*)s1;
|
||||||
const unsigned __int64* b64 = (const unsigned __int64*)s2;
|
const unsigned __int64* b64 = (const unsigned __int64*)s2;
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
!include $(BASEDIR)\makefile.def
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
TARGETNAME=libc
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=LIBRARY
|
||||||
|
FLAVOR=LIBC
|
||||||
|
SOURCES=@/code/common/libc.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!include $(BASEDIR)\makefile.def
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
TARGETNAME=printf
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=LIBRARY
|
||||||
|
FLAVOR=COMMON
|
||||||
|
SOURCES=@/code/common/printf.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!include $(BASEDIR)\makefile.def
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
TARGETNAME=ntlddk
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=LIBRARY
|
||||||
|
FLAVOR=DRIVER
|
||||||
|
SOURCES=@/code/ddk/pci_caps.c
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
; drivers.ini
|
; Driver dependency graph.
|
||||||
|
; [class.id] declares a provider class; [driver.id] declares a driver.
|
||||||
|
; requires= Providers that must succeed; after= providers that must settle.
|
||||||
|
; start=boot loads during bootstrap; start=runtime loads after boot.
|
||||||
|
|
||||||
[class.bus]
|
[class.bus]
|
||||||
|
|
||||||
@@ -88,3 +91,9 @@ class=network-adapter
|
|||||||
image=rtl816x.sys
|
image=rtl816x.sys
|
||||||
start=runtime
|
start=runtime
|
||||||
class=network-adapter
|
class=network-adapter
|
||||||
|
|
||||||
|
[driver.acpi]
|
||||||
|
image=acpi.sys
|
||||||
|
start=boot
|
||||||
|
critical=false
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DIRS=hda
|
||||||
+19
-114
@@ -6,10 +6,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static DRIVER_OBJECT gHdaDriver;
|
static DRIVER_OBJECT gHdaDriver;
|
||||||
static HDA_CONTROLLER* gHdaControllers[HDA_MAX_CONTROLLERS];
|
|
||||||
static uint32_t gHdaControllerCount;
|
|
||||||
static SPINLOCK gHdaRegistryLock = SPINLOCK_INIT;
|
|
||||||
|
|
||||||
static const IO_DEVICE_ID gHdaIds[] = {
|
static const IO_DEVICE_ID gHdaIds[] = {
|
||||||
{ IoBusPci, { "PCI\\VEN_8086&DEV_2668", sizeof("PCI\\VEN_8086&DEV_2668") - 1u } },
|
{ IoBusPci, { "PCI\\VEN_8086&DEV_2668", sizeof("PCI\\VEN_8086&DEV_2668") - 1u } },
|
||||||
{ IoBusPci, { "PCI\\VEN_15AD&DEV_1977", sizeof("PCI\\VEN_15AD&DEV_1977") - 1u } },
|
{ IoBusPci, { "PCI\\VEN_15AD&DEV_1977", sizeof("PCI\\VEN_15AD&DEV_1977") - 1u } },
|
||||||
@@ -21,79 +17,14 @@ static const IO_DRIVER_ID_TABLE gHdaIdTable = {
|
|||||||
sizeof(gHdaIds) / sizeof(gHdaIds[0]),
|
sizeof(gHdaIds) / sizeof(gHdaIds[0]),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Registers a controller in the shared interrupt scan set.
|
// Handles the interrupt for its owning HDA controller.
|
||||||
static KSTATUS HdaRegisterController(HDA_CONTROLLER* controller) {
|
static void HdaIsr(void* context) {
|
||||||
if (!controller)
|
HDA_CONTROLLER* controller = (HDA_CONTROLLER*)context;
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
if (controller && controller->Magic == HDA_CONTROLLER_MAGIC)
|
||||||
|
HdaHandleInterrupt(controller);
|
||||||
uintptr_t flags = KeAcquireSpinlock(&gHdaRegistryLock);
|
|
||||||
for (uint32_t index = 0; index < gHdaControllerCount; index++) {
|
|
||||||
if (gHdaControllers[index] == controller) {
|
|
||||||
KeReleaseSpinlock(&gHdaRegistryLock, flags);
|
|
||||||
return NTLSTATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (gHdaControllerCount == HDA_MAX_CONTROLLERS) {
|
|
||||||
KeReleaseSpinlock(&gHdaRegistryLock, flags);
|
|
||||||
return NTLSTATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
gHdaControllers[gHdaControllerCount++] = controller;
|
|
||||||
KeReleaseSpinlock(&gHdaRegistryLock, flags);
|
|
||||||
return NTLSTATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes a controller from the shared interrupt scan set.
|
|
||||||
static void HdaUnregisterController(HDA_CONTROLLER* controller) {
|
|
||||||
if (!controller)
|
|
||||||
return;
|
|
||||||
|
|
||||||
uintptr_t flags = KeAcquireSpinlock(&gHdaRegistryLock);
|
|
||||||
for (uint32_t index = 0; index < gHdaControllerCount; index++) {
|
|
||||||
if (gHdaControllers[index] != controller)
|
|
||||||
continue;
|
|
||||||
gHdaControllers[index] = gHdaControllers[gHdaControllerCount - 1u];
|
|
||||||
gHdaControllers[gHdaControllerCount - 1u] = (HDA_CONTROLLER*)0;
|
|
||||||
gHdaControllerCount--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
KeReleaseSpinlock(&gHdaRegistryLock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dispatches a hardware interrupt to every live HDA controller.
|
|
||||||
static void HdaIsr(void) {
|
|
||||||
DEVICE_OBJECT* devices[HDA_MAX_CONTROLLERS];
|
|
||||||
uint32_t count = 0;
|
|
||||||
|
|
||||||
uintptr_t flags = KeAcquireSpinlock(&gHdaRegistryLock);
|
|
||||||
count = gHdaControllerCount;
|
|
||||||
if (count > HDA_MAX_CONTROLLERS)
|
|
||||||
count = HDA_MAX_CONTROLLERS;
|
|
||||||
for (uint32_t index = 0; index < count; index++) {
|
|
||||||
HDA_CONTROLLER* controller = gHdaControllers[index];
|
|
||||||
devices[index] = controller ? controller->Fdo : (DEVICE_OBJECT*)0;
|
|
||||||
if (devices[index])
|
|
||||||
IoReferenceDeviceObject(devices[index]);
|
|
||||||
}
|
|
||||||
KeReleaseSpinlock(&gHdaRegistryLock, flags);
|
|
||||||
|
|
||||||
for (uint32_t index = 0; index < count; index++) {
|
|
||||||
DEVICE_OBJECT* device = devices[index];
|
|
||||||
if (!device)
|
|
||||||
continue;
|
|
||||||
HDA_CONTROLLER* controller = (HDA_CONTROLLER*)device->DeviceExtension;
|
|
||||||
if (controller && controller->Magic == HDA_CONTROLLER_MAGIC)
|
|
||||||
HdaHandleInterrupt(controller);
|
|
||||||
IoDereferenceDeviceObject(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Registers the global ISR once for each kernel IRQ slot used by HDA.
|
|
||||||
static KSTATUS HdaRegisterIrq(uint8_t irq) {
|
|
||||||
if (irq >= 24u)
|
|
||||||
return NTLSTATUS_NOT_SUPPORTED;
|
|
||||||
KeIrqRegister(irq, HdaIsr);
|
|
||||||
return NTLSTATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maps BAR0 and validates the stream-descriptor aperture described by GCAP.
|
// Maps BAR0 and validates the stream-descriptor aperture described by GCAP.
|
||||||
static KSTATUS HdaMapRegisters(HDA_CONTROLLER* controller) {
|
static KSTATUS HdaMapRegisters(HDA_CONTROLLER* controller) {
|
||||||
@@ -149,29 +80,14 @@ static KSTATUS HdaMapRegisters(HDA_CONTROLLER* controller) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configures MSI first and enables INTx only after MSI setup reports failure.
|
// Connects the controller interrupt using the PCI bus routing policy.
|
||||||
static KSTATUS HdaConfigureInterrupt(HDA_CONTROLLER* controller) {
|
static KSTATUS HdaConfigureInterrupt(HDA_CONTROLLER* controller) {
|
||||||
KSTATUS status = PciEnableMsiAuto(controller->Pdo, &controller->Irq);
|
controller->InterruptRequest.Routine = HdaIsr;
|
||||||
if (KSUCCESS(status)) {
|
controller->InterruptRequest.Context = controller;
|
||||||
controller->UsingMsi = true;
|
controller->InterruptRequest.Affinity = 0;
|
||||||
return NTLSTATUS_SUCCESS;
|
controller->InterruptRequest.Interrupt = (KE_INTERRUPT*)0;
|
||||||
}
|
return PciConnectInterrupts(controller->Pdo, &controller->InterruptRequest,
|
||||||
|
1u, &controller->UsingMsi);
|
||||||
DbgPrint(
|
|
||||||
"HDA: MSI setup failed status=0x%x; attempting explicit INTx fallback\n",
|
|
||||||
status);
|
|
||||||
controller->UsingMsi = false;
|
|
||||||
status = PciGetInterrupt(controller->Pdo, &controller->Irq);
|
|
||||||
if (!KSUCCESS(status))
|
|
||||||
return status;
|
|
||||||
if (controller->Irq == 0xFFu || controller->Irq >= 24u)
|
|
||||||
return NTLSTATUS_NOT_SUPPORTED;
|
|
||||||
|
|
||||||
status = PciEnableDevice(controller->Pdo,
|
|
||||||
PCI_ENABLE_MEMORY |
|
|
||||||
PCI_ENABLE_BUSMASTER |
|
|
||||||
PCI_ENABLE_INTX);
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Waits until queued or active interrupt work no longer references the controller.
|
// Waits until queued or active interrupt work no longer references the controller.
|
||||||
@@ -214,9 +130,6 @@ static KSTATUS HdaStartDevice(HDA_CONTROLLER* controller) {
|
|||||||
if (!KSUCCESS(status))
|
if (!KSUCCESS(status))
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
status = HdaConfigureInterrupt(controller);
|
|
||||||
if (!KSUCCESS(status))
|
|
||||||
return status;
|
|
||||||
|
|
||||||
status = HdaAllocateDma(controller);
|
status = HdaAllocateDma(controller);
|
||||||
if (!KSUCCESS(status))
|
if (!KSUCCESS(status))
|
||||||
@@ -237,21 +150,13 @@ static KSTATUS HdaStartDevice(HDA_CONTROLLER* controller) {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = HdaRegisterController(controller);
|
status = HdaConfigureInterrupt(controller);
|
||||||
if (!KSUCCESS(status)) {
|
if (!KSUCCESS(status)) {
|
||||||
HdaStopRecoveryWorker(controller);
|
HdaStopRecoveryWorker(controller);
|
||||||
HdaQuiesceController(controller);
|
HdaQuiesceController(controller);
|
||||||
HdaReleaseDma(controller);
|
HdaReleaseDma(controller);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
status = HdaRegisterIrq(controller->Irq);
|
|
||||||
if (!KSUCCESS(status)) {
|
|
||||||
HdaUnregisterController(controller);
|
|
||||||
HdaStopRecoveryWorker(controller);
|
|
||||||
HdaQuiesceController(controller);
|
|
||||||
HdaReleaseDma(controller);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
controller->Started = true;
|
controller->Started = true;
|
||||||
controller->Fdo->PnpState = DevicePnpStarted;
|
controller->Fdo->PnpState = DevicePnpStarted;
|
||||||
@@ -261,7 +166,8 @@ static KSTATUS HdaStartDevice(HDA_CONTROLLER* controller) {
|
|||||||
status != NTLSTATUS_NOT_FOUND) {
|
status != NTLSTATUS_NOT_FOUND) {
|
||||||
controller->Started = false;
|
controller->Started = false;
|
||||||
controller->Fdo->PnpState = DevicePnpNotStarted;
|
controller->Fdo->PnpState = DevicePnpNotStarted;
|
||||||
HdaUnregisterController(controller);
|
if (controller->InterruptRequest.Interrupt)
|
||||||
|
PciDisconnectInterrupts(controller->Pdo, &controller->InterruptRequest, 1u);
|
||||||
HdaStopRecoveryWorker(controller);
|
HdaStopRecoveryWorker(controller);
|
||||||
HdaQuiesceController(controller);
|
HdaQuiesceController(controller);
|
||||||
HdaReleaseDma(controller);
|
HdaReleaseDma(controller);
|
||||||
@@ -302,7 +208,8 @@ static KSTATUS HdaDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
|||||||
case IRP_MN_SURPRISE_REMOVAL:
|
case IRP_MN_SURPRISE_REMOVAL:
|
||||||
controller->Started = false;
|
controller->Started = false;
|
||||||
controller->SurpriseRemoved = true;
|
controller->SurpriseRemoved = true;
|
||||||
HdaUnregisterController(controller);
|
if (controller->InterruptRequest.Interrupt)
|
||||||
|
PciDisconnectInterrupts(controller->Pdo, &controller->InterruptRequest, 1u);
|
||||||
HdaStopRecoveryWorker(controller);
|
HdaStopRecoveryWorker(controller);
|
||||||
KSTATUS surpriseDpcStatus =
|
KSTATUS surpriseDpcStatus =
|
||||||
HdaWaitForControllerInterruptWorkIdle(controller);
|
HdaWaitForControllerInterruptWorkIdle(controller);
|
||||||
@@ -320,7 +227,8 @@ static KSTATUS HdaDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
|||||||
if (!controller->SurpriseRemoved && controller->Registers)
|
if (!controller->SurpriseRemoved && controller->Registers)
|
||||||
HdaWrite32(controller, HDA_REG_INTCTL, 0);
|
HdaWrite32(controller, HDA_REG_INTCTL, 0);
|
||||||
controller->Started = false;
|
controller->Started = false;
|
||||||
HdaUnregisterController(controller);
|
if (controller->InterruptRequest.Interrupt)
|
||||||
|
PciDisconnectInterrupts(controller->Pdo, &controller->InterruptRequest, 1u);
|
||||||
HdaStopRecoveryWorker(controller);
|
HdaStopRecoveryWorker(controller);
|
||||||
KSTATUS dpcStatus = HdaWaitForControllerInterruptWorkIdle(controller);
|
KSTATUS dpcStatus = HdaWaitForControllerInterruptWorkIdle(controller);
|
||||||
if (!KSUCCESS(dpcStatus)) {
|
if (!KSUCCESS(dpcStatus)) {
|
||||||
@@ -366,7 +274,6 @@ static KSTATUS HdaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDevice
|
|||||||
controller->Magic = HDA_CONTROLLER_MAGIC;
|
controller->Magic = HDA_CONTROLLER_MAGIC;
|
||||||
controller->Fdo = fdo;
|
controller->Fdo = fdo;
|
||||||
controller->Pdo = physicalDeviceObject;
|
controller->Pdo = physicalDeviceObject;
|
||||||
controller->Irq = 0xFFu;
|
|
||||||
controller->StateLock = (SPINLOCK)SPINLOCK_INIT;
|
controller->StateLock = (SPINLOCK)SPINLOCK_INIT;
|
||||||
controller->Output.StreamTag = HDA_OUTPUT_STREAM_TAG;
|
controller->Output.StreamTag = HDA_OUTPUT_STREAM_TAG;
|
||||||
|
|
||||||
@@ -382,8 +289,6 @@ static KSTATUS HdaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDevice
|
|||||||
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
||||||
(void)module;
|
(void)module;
|
||||||
|
|
||||||
gHdaControllerCount = 0;
|
|
||||||
memset(gHdaControllers, 0, sizeof(gHdaControllers));
|
|
||||||
|
|
||||||
memset(&gHdaDriver, 0, sizeof(gHdaDriver));
|
memset(&gHdaDriver, 0, sizeof(gHdaDriver));
|
||||||
IoInitializeDriverObject(&gHdaDriver, SYS_SV_LITERAL("hda"));
|
IoInitializeDriverObject(&gHdaDriver, SYS_SV_LITERAL("hda"));
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ struct HDA_CONTROLLER {
|
|||||||
uint8_t BidirectionalStreamCount;
|
uint8_t BidirectionalStreamCount;
|
||||||
uint8_t TotalStreamCount;
|
uint8_t TotalStreamCount;
|
||||||
uint16_t CodecMask;
|
uint16_t CodecMask;
|
||||||
uint8_t Irq;
|
PCI_INTERRUPT_REQUEST InterruptRequest;
|
||||||
bool UsingMsi;
|
bool UsingMsi;
|
||||||
bool Started;
|
bool Started;
|
||||||
bool Removed;
|
bool Removed;
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
!include $(BASEDIR)\makefile.def
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
TARGETNAME=hda
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=DRIVER
|
||||||
|
FLAVOR=DRIVER
|
||||||
|
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\pci.lib"
|
||||||
|
EXTRA_LFLAGS=/NOENTRY
|
||||||
|
SOURCES=@/code/drivers/audio/hda/hda.c @/code/drivers/audio/hda/hda_transport.c @/code/drivers/audio/hda/hda_codec.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DIRS=pci usb
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!include $(BASEDIR)\makefile.def
|
||||||
+297
-78
@@ -26,13 +26,12 @@ static uint32_t gPciDeviceCount;
|
|||||||
#define PCI_MMIO_VA_LIMIT 0xFFFF980000000000ULL
|
#define PCI_MMIO_VA_LIMIT 0xFFFF980000000000ULL
|
||||||
|
|
||||||
static uintptr_t gPciMmioNext = PCI_MMIO_VA_BASE;
|
static uintptr_t gPciMmioNext = PCI_MMIO_VA_BASE;
|
||||||
|
static SPINLOCK gPciMmioLock = SPINLOCK_INIT;
|
||||||
|
|
||||||
// Implements the align Up64 operation.
|
|
||||||
static uint64_t PciAlignUp64(uint64_t value, uint64_t alignment) {
|
static uint64_t PciAlignUp64(uint64_t value, uint64_t alignment) {
|
||||||
return (value + alignment - 1u) & ~(alignment - 1u);
|
return (value + alignment - 1u) & ~(alignment - 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the default Mmio Flags operation.
|
|
||||||
static uint64_t PciDefaultMmioFlags(void) {
|
static uint64_t PciDefaultMmioFlags(void) {
|
||||||
return NTL_DDK_PAGE_PRESENT | NTL_DDK_PAGE_WRITE | NTL_DDK_PAGE_CACHE_UC | NTL_DDK_PAGE_NX;
|
return NTL_DDK_PAGE_PRESENT | NTL_DDK_PAGE_WRITE | NTL_DDK_PAGE_CACHE_UC | NTL_DDK_PAGE_NX;
|
||||||
}
|
}
|
||||||
@@ -43,13 +42,15 @@ static KSTATUS PciAllocateMmioVa(uint64_t length, uintptr_t* outVa) {
|
|||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
uint64_t alignedLength = PciAlignUp64(length, NTL_DDK_PAGE_SIZE);
|
uint64_t alignedLength = PciAlignUp64(length, NTL_DDK_PAGE_SIZE);
|
||||||
|
uintptr_t cookie = KeAcquireSpinlock(&gPciMmioLock);
|
||||||
uintptr_t va = (uintptr_t)PciAlignUp64((uint64_t)gPciMmioNext, NTL_DDK_PAGE_SIZE);
|
uintptr_t va = (uintptr_t)PciAlignUp64((uint64_t)gPciMmioNext, NTL_DDK_PAGE_SIZE);
|
||||||
if (va < PCI_MMIO_VA_BASE || va >= PCI_MMIO_VA_LIMIT)
|
if (va < PCI_MMIO_VA_BASE || va >= PCI_MMIO_VA_LIMIT ||
|
||||||
|
alignedLength > (uint64_t)(PCI_MMIO_VA_LIMIT - va)) {
|
||||||
|
KeReleaseSpinlock(&gPciMmioLock, cookie);
|
||||||
return NTLSTATUS_NO_MEMORY;
|
return NTLSTATUS_NO_MEMORY;
|
||||||
if (alignedLength > (uint64_t)(PCI_MMIO_VA_LIMIT - va))
|
}
|
||||||
return NTLSTATUS_NO_MEMORY;
|
|
||||||
|
|
||||||
gPciMmioNext = va + (uintptr_t)alignedLength;
|
gPciMmioNext = va + (uintptr_t)alignedLength;
|
||||||
|
KeReleaseSpinlock(&gPciMmioLock, cookie);
|
||||||
*outVa = va;
|
*outVa = va;
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -64,31 +65,26 @@ static bool PciIsPdo(DEVICE_OBJECT* pdo, PCI_PDO_EXTENSION** outExt) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the raw Read32 operation.
|
|
||||||
static uint32_t PciRawRead32(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset) {
|
static uint32_t PciRawRead32(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset) {
|
||||||
if (offset > 0xFCu) return 0xFFFFFFFFu;
|
if (offset > 0xFCu) return 0xFFFFFFFFu;
|
||||||
return KePciReadConfig32(0, bus, dev, fn, offset & 0xFCu);
|
return KePciReadConfig32(0, bus, dev, fn, offset & 0xFCu);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the raw Write32 operation.
|
|
||||||
static void PciRawWrite32(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, uint32_t value) {
|
static void PciRawWrite32(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, uint32_t value) {
|
||||||
if (offset > 0xFCu) return;
|
if (offset > 0xFCu) return;
|
||||||
KePciWriteConfig32(0, bus, dev, fn, offset & 0xFCu, value);
|
KePciWriteConfig32(0, bus, dev, fn, offset & 0xFCu, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the raw Read8 operation.
|
|
||||||
static uint8_t PciRawRead8(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset) {
|
static uint8_t PciRawRead8(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset) {
|
||||||
uint32_t v = PciRawRead32(bus, dev, fn, offset);
|
uint32_t v = PciRawRead32(bus, dev, fn, offset);
|
||||||
return (uint8_t)(v >> ((offset & 3u) * 8u));
|
return (uint8_t)(v >> ((offset & 3u) * 8u));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the raw Read16 operation.
|
|
||||||
static uint16_t PciRawRead16(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset) {
|
static uint16_t PciRawRead16(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset) {
|
||||||
uint32_t v = PciRawRead32(bus, dev, fn, offset);
|
uint32_t v = PciRawRead32(bus, dev, fn, offset);
|
||||||
return (uint16_t)(v >> ((offset & 2u) * 8u));
|
return (uint16_t)(v >> ((offset & 2u) * 8u));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the raw Write8 operation.
|
|
||||||
static void PciRawWrite8(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, uint8_t value) {
|
static void PciRawWrite8(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, uint8_t value) {
|
||||||
uint16_t aligned = offset & ~3u;
|
uint16_t aligned = offset & ~3u;
|
||||||
uint32_t shift = (offset & 3u) * 8u;
|
uint32_t shift = (offset & 3u) * 8u;
|
||||||
@@ -98,7 +94,6 @@ static void PciRawWrite8(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset,
|
|||||||
PciRawWrite32(bus, dev, fn, aligned, old);
|
PciRawWrite32(bus, dev, fn, aligned, old);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the raw Write16 operation.
|
|
||||||
static void PciRawWrite16(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, uint16_t value) {
|
static void PciRawWrite16(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, uint16_t value) {
|
||||||
uint16_t aligned = offset & ~3u;
|
uint16_t aligned = offset & ~3u;
|
||||||
uint32_t shift = (offset & 2u) * 8u;
|
uint32_t shift = (offset & 2u) * 8u;
|
||||||
@@ -108,7 +103,6 @@ static void PciRawWrite16(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset,
|
|||||||
PciRawWrite32(bus, dev, fn, aligned, old);
|
PciRawWrite32(bus, dev, fn, aligned, old);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the bar Size From Mask operation.
|
|
||||||
static uint64_t PciBarSizeFromMask(uint64_t mask, uint64_t baseMask) {
|
static uint64_t PciBarSizeFromMask(uint64_t mask, uint64_t baseMask) {
|
||||||
uint64_t sizeMask = mask & baseMask;
|
uint64_t sizeMask = mask & baseMask;
|
||||||
if (!sizeMask || sizeMask == baseMask)
|
if (!sizeMask || sizeMask == baseMask)
|
||||||
@@ -116,7 +110,6 @@ static uint64_t PciBarSizeFromMask(uint64_t mask, uint64_t baseMask) {
|
|||||||
return (~sizeMask + 1u) & baseMask;
|
return (~sizeMask + 1u) & baseMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the header Bar Count operation.
|
|
||||||
static uint8_t PciHeaderBarCount(uint8_t headerType) {
|
static uint8_t PciHeaderBarCount(uint8_t headerType) {
|
||||||
switch (headerType & PCI_HEADER_TYPE_MASK) {
|
switch (headerType & PCI_HEADER_TYPE_MASK) {
|
||||||
case 0x00: return 6;
|
case 0x00: return 6;
|
||||||
@@ -126,7 +119,6 @@ static uint8_t PciHeaderBarCount(uint8_t headerType) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the decode Bars operation.
|
|
||||||
static void PciDecodeBars(PCI_PDO_EXTENSION* ext) {
|
static void PciDecodeBars(PCI_PDO_EXTENSION* ext) {
|
||||||
uint8_t barCount = PciHeaderBarCount(ext->Info.HeaderType);
|
uint8_t barCount = PciHeaderBarCount(ext->Info.HeaderType);
|
||||||
for (uint8_t i = 0; i < PCI_MAX_BARS; i++) {
|
for (uint8_t i = 0; i < PCI_MAX_BARS; i++) {
|
||||||
@@ -398,7 +390,6 @@ static KSTATUS PciCreatePdo(uint8_t bus, uint8_t dev, uint8_t fn) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the enumerate Bus operation.
|
|
||||||
static void PciEnumerateBus(void) {
|
static void PciEnumerateBus(void) {
|
||||||
for (uint32_t bus = 0; bus < 256u; bus++) {
|
for (uint32_t bus = 0; bus < 256u; bus++) {
|
||||||
for (uint32_t dev = 0; dev < 32u; dev++) {
|
for (uint32_t dev = 0; dev < 32u; dev++) {
|
||||||
@@ -440,7 +431,6 @@ static KSTATUS PciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the driver Abi Version operation.
|
|
||||||
__declspec(dllexport) uint32_t PciDriverAbiVersion(void) {
|
__declspec(dllexport) uint32_t PciDriverAbiVersion(void) {
|
||||||
return 1u;
|
return 1u;
|
||||||
}
|
}
|
||||||
@@ -601,77 +591,306 @@ static uint8_t PciFindCapability(PCI_PDO_EXTENSION* ext, uint8_t capId) {
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enables msi.
|
// PCI owns message programming, while the kernel owns CPU/vector placement.
|
||||||
__declspec(dllexport) KSTATUS PciEnableMsi(DEVICE_OBJECT* pdo, uint8_t irqSlot) {
|
typedef struct PCI_MESSAGE_CONTEXT {
|
||||||
|
DEVICE_OBJECT* Pdo;
|
||||||
|
uint32_t TableOffset;
|
||||||
|
uint16_t Capability;
|
||||||
|
uint8_t Msix;
|
||||||
|
uint8_t Reserved;
|
||||||
|
} PCI_MESSAGE_CONTEXT;
|
||||||
|
|
||||||
|
static KSTATUS PciUpdateMessageRoute(void* opaque,
|
||||||
|
KE_INTERRUPT_MESSAGE_OPERATION operation, const NTL_DDK_MSI_MESSAGE* message) {
|
||||||
|
PCI_MESSAGE_CONTEXT* ctx = (PCI_MESSAGE_CONTEXT*)opaque;
|
||||||
PCI_PDO_EXTENSION* ext;
|
PCI_PDO_EXTENSION* ext;
|
||||||
if (!PciIsPdo(pdo, &ext))
|
if (!ctx || !PciIsPdo(ctx->Pdo, &ext)) return NTLSTATUS_INVALID_PARAMETER;
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
uint8_t bus = ext->Info.Address.Bus, dev = ext->Info.Address.Device;
|
||||||
if (irqSlot >= 24u)
|
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
uint8_t cap = PciFindCapability(ext, PCI_CAP_ID_MSI);
|
|
||||||
if (!cap)
|
|
||||||
return NTLSTATUS_NOT_SUPPORTED;
|
|
||||||
|
|
||||||
uint8_t bus = ext->Info.Address.Bus;
|
|
||||||
uint8_t dev = ext->Info.Address.Device;
|
|
||||||
uint8_t fn = ext->Info.Address.Function;
|
uint8_t fn = ext->Info.Address.Function;
|
||||||
|
if (ctx->Msix) {
|
||||||
uint16_t control = PciRawRead16(bus, dev, fn, (uint16_t)(cap + 2u));
|
if (!ext->MsixTable || ctx->TableOffset > ext->MsixMappedLength ||
|
||||||
bool is64 = (control & PCI_MSI_CTRL_64BIT) != 0;
|
ext->MsixMappedLength - ctx->TableOffset < 16u)
|
||||||
bool pvm = (control & PCI_MSI_CTRL_PVM) != 0;
|
return NTLSTATUS_DEVICE_ERROR;
|
||||||
NTL_DDK_MSI_MESSAGE message;
|
volatile uint32_t* entry = (volatile uint32_t*)(ext->MsixTable + ctx->TableOffset);
|
||||||
KSTATUS messageStatus = KeIrqComposeMsiMessage(irqSlot, &message);
|
if (operation == KeInterruptMessageQuiesce) {
|
||||||
if (!KSUCCESS(messageStatus))
|
entry[3] = 1u;
|
||||||
return messageStatus;
|
} else if (operation == KeInterruptMessageProgram && message) {
|
||||||
|
entry[0] = (uint32_t)message->Address;
|
||||||
PciRawWrite32(bus, dev, fn, (uint16_t)(cap + 4u), (uint32_t)message.Address);
|
entry[1] = (uint32_t)(message->Address >> 32);
|
||||||
if (is64) {
|
entry[2] = message->Data;
|
||||||
PciRawWrite32(bus, dev, fn, (uint16_t)(cap + 8u), (uint32_t)(message.Address >> 32));
|
} else if (operation == KeInterruptMessageResume) {
|
||||||
PciRawWrite16(bus, dev, fn, (uint16_t)(cap + 12u), (uint16_t)message.Data);
|
entry[3] = 0u;
|
||||||
if (pvm)
|
} else return NTLSTATUS_INVALID_PARAMETER;
|
||||||
PciRawWrite32(bus, dev, fn, (uint16_t)(cap + 16u), 0);
|
(void)entry[3];
|
||||||
} else {
|
return NTLSTATUS_SUCCESS;
|
||||||
PciRawWrite16(bus, dev, fn, (uint16_t)(cap + 8u), (uint16_t)message.Data);
|
|
||||||
if (pvm)
|
|
||||||
PciRawWrite32(bus, dev, fn, (uint16_t)(cap + 12u), 0);
|
|
||||||
}
|
}
|
||||||
|
uint16_t control = PciRawRead16(bus, dev, fn, ctx->Capability + 2u);
|
||||||
control &= (uint16_t)~PCI_MSI_CTRL_MME_MASK;
|
bool is64 = (control & PCI_MSI_CTRL_64BIT) != 0;
|
||||||
control |= PCI_MSI_CTRL_ENABLE;
|
// MSI per-vector masking preserves pending messages during retargeting.
|
||||||
PciRawWrite16(bus, dev, fn, (uint16_t)(cap + 2u), control);
|
// Devices without PVM retain their initial affinity until disconnect.
|
||||||
|
if (!(control & PCI_MSI_CTRL_PVM)) return NTLSTATUS_NOT_SUPPORTED;
|
||||||
uint16_t cmd = PciRawRead16(bus, dev, fn, PCI_REG_COMMAND_STATUS);
|
uint16_t maskOffset = ctx->Capability + (is64 ? 16u : 12u);
|
||||||
cmd |= PCI_COMMAND_INTX_DISABLE;
|
if (operation == KeInterruptMessageQuiesce) {
|
||||||
PciRawWrite16(bus, dev, fn, PCI_REG_COMMAND_STATUS, cmd);
|
uint32_t mask = PciRawRead32(bus, dev, fn, maskOffset);
|
||||||
|
PciRawWrite32(bus, dev, fn, maskOffset, mask | 1u);
|
||||||
DbgPrint("pci: MSI enabled %02x:%02x.%u cap=0x%02x vector=0x%02x irqslot=%u %s\n",
|
(void)PciRawRead32(bus, dev, fn, maskOffset);
|
||||||
bus, dev, fn, cap, (unsigned)(message.Data & 0xFFu), irqSlot, is64 ? "64-bit" : "32-bit");
|
} else if (operation == KeInterruptMessageProgram && message) {
|
||||||
|
PciRawWrite32(bus, dev, fn, ctx->Capability + 4u, (uint32_t)message->Address);
|
||||||
|
if (is64) {
|
||||||
|
PciRawWrite32(bus, dev, fn, ctx->Capability + 8u,
|
||||||
|
(uint32_t)(message->Address >> 32));
|
||||||
|
PciRawWrite16(bus, dev, fn, ctx->Capability + 12u, (uint16_t)message->Data);
|
||||||
|
} else PciRawWrite16(bus, dev, fn, ctx->Capability + 8u, (uint16_t)message->Data);
|
||||||
|
} else if (operation == KeInterruptMessageResume) {
|
||||||
|
uint32_t mask = PciRawRead32(bus, dev, fn, maskOffset);
|
||||||
|
PciRawWrite32(bus, dev, fn, maskOffset, mask & ~1u);
|
||||||
|
(void)PciRawRead32(bus, dev, fn, maskOffset);
|
||||||
|
} else return NTLSTATUS_INVALID_PARAMETER;
|
||||||
|
(void)PciRawRead16(bus, dev, fn, ctx->Capability + 2u);
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enables a single MSI vector, allocating the nt-lite IRQ slot internally.
|
static KSTATUS PciBindMessage(DEVICE_OBJECT* pdo, PCI_INTERRUPT_REQUEST* request,
|
||||||
__declspec(dllexport) KSTATUS PciEnableMsiAuto(DEVICE_OBJECT* pdo, uint8_t* outIrqSlot) {
|
uint8_t msix, uint16_t capability, uint32_t tableOffset) {
|
||||||
PCI_PDO_EXTENSION* ext;
|
PCI_MESSAGE_CONTEXT* ctx = (PCI_MESSAGE_CONTEXT*)MmAllocatePool(sizeof(*ctx));
|
||||||
if (!outIrqSlot || !PciIsPdo(pdo, &ext))
|
if (!ctx) return NTLSTATUS_NO_MEMORY;
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
ctx->Pdo = pdo;
|
||||||
|
ctx->Msix = msix;
|
||||||
if (!PciFindCapability(ext, PCI_CAP_ID_MSI))
|
ctx->Capability = capability;
|
||||||
return NTLSTATUS_NOT_SUPPORTED;
|
ctx->TableOffset = tableOffset;
|
||||||
|
ctx->Reserved = 0;
|
||||||
uint8_t irq = 0xFFu;
|
KSTATUS st = KeInterruptBindMessageSource(request->Interrupt, PciUpdateMessageRoute, ctx);
|
||||||
KSTATUS st = KeIrqAllocateMsiVector(&irq);
|
if (!KSUCCESS(st)) {
|
||||||
if (!KSUCCESS(st))
|
MmFreePool(ctx);
|
||||||
return st;
|
return st;
|
||||||
|
}
|
||||||
st = PciEnableMsi(pdo, irq);
|
request->BusContext = ctx;
|
||||||
if (!KSUCCESS(st))
|
|
||||||
return st;
|
|
||||||
|
|
||||||
*outIrqSlot = irq;
|
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Programs a pre-allocated interrupt group. All routes exist before device delivery begins.
|
||||||
|
static KSTATUS PciConnectMsix(DEVICE_OBJECT* pdo, PCI_PDO_EXTENSION* ext,
|
||||||
|
PCI_INTERRUPT_REQUEST* requests, uint32_t count) {
|
||||||
|
uint8_t cap = PciFindCapability(ext, PCI_CAP_ID_MSIX);
|
||||||
|
if (!cap) return NTLSTATUS_NOT_SUPPORTED;
|
||||||
|
uint8_t bus = ext->Info.Address.Bus, dev = ext->Info.Address.Device;
|
||||||
|
uint8_t fn = ext->Info.Address.Function;
|
||||||
|
uint16_t control = PciRawRead16(bus, dev, fn, cap + 2u);
|
||||||
|
uint32_t size = (control & 0x7FFu) + 1u;
|
||||||
|
if (count > size) return NTLSTATUS_NOT_SUPPORTED;
|
||||||
|
uint32_t table = PciRawRead32(bus, dev, fn, cap + 4u);
|
||||||
|
uint32_t bir = table & 7u, offset = table & ~7u;
|
||||||
|
if (bir >= PCI_MAX_BARS) return NTLSTATUS_DEVICE_ERROR;
|
||||||
|
PCI_BAR bar;
|
||||||
|
KSTATUS st = PciGetBar(pdo, (uint8_t)bir, &bar);
|
||||||
|
if (!KSUCCESS(st) || (bar.Type != PciBarMemory32 && bar.Type != PciBarMemory64) ||
|
||||||
|
bar.Length < offset || count > (bar.Length - offset) / 16u)
|
||||||
|
return NTLSTATUS_NOT_SUPPORTED;
|
||||||
|
uint16_t command = PciRawRead16(bus, dev, fn, PCI_REG_COMMAND_STATUS);
|
||||||
|
if (!(command & PCI_COMMAND_MEMORY_SPACE)) {
|
||||||
|
DbgPrint("pci: MSI-X requires enabled memory decoding at %02x:%02x.%u\n",
|
||||||
|
bus, dev, fn);
|
||||||
|
return NTLSTATUS_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ext->MsixTable) {
|
||||||
|
volatile uint8_t* mapped = (volatile uint8_t*)0;
|
||||||
|
uint64_t mappedLength = 0;
|
||||||
|
st = PciMapBar(pdo, (uint8_t)bir,
|
||||||
|
NTL_DDK_PAGE_PRESENT | NTL_DDK_PAGE_WRITE | NTL_DDK_PAGE_CACHE_UC | NTL_DDK_PAGE_NX,
|
||||||
|
(void**)&mapped, &mappedLength);
|
||||||
|
if (!KSUCCESS(st)) return st;
|
||||||
|
ext->MsixTable = mapped;
|
||||||
|
ext->MsixMappedLength = mappedLength;
|
||||||
|
ext->MsixBarIndex = (uint8_t)bir;
|
||||||
|
}
|
||||||
|
// A persistent per-PDO mapping prevents repeated BAR allocations on reconnect.
|
||||||
|
if (ext->MsixBarIndex != bir || ext->MsixMappedLength < offset ||
|
||||||
|
count > (ext->MsixMappedLength - offset) / 16u)
|
||||||
|
return NTLSTATUS_DEVICE_ERROR;
|
||||||
|
volatile uint8_t* mapped = ext->MsixTable;
|
||||||
|
|
||||||
|
// Mask the function and turn off stale firmware MSI before programming MSI-X.
|
||||||
|
PciRawWrite16(bus, dev, fn, cap + 2u, (control | 0x4000u) & ~0x8000u);
|
||||||
|
uint8_t msiCap = PciFindCapability(ext, PCI_CAP_ID_MSI);
|
||||||
|
if (msiCap) {
|
||||||
|
uint16_t msiControl = PciRawRead16(bus, dev, fn, msiCap + 2u);
|
||||||
|
PciRawWrite16(bus, dev, fn, msiCap + 2u,
|
||||||
|
msiControl & (uint16_t)~PCI_MSI_CTRL_ENABLE);
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
st = KeInterruptReserveMessage(requests[i].Affinity, requests[i].Routine,
|
||||||
|
requests[i].Context, &requests[i].Interrupt);
|
||||||
|
if (!KSUCCESS(st)) goto failed;
|
||||||
|
NTL_DDK_MSI_MESSAGE msg;
|
||||||
|
st = KeInterruptComposeMessage(requests[i].Interrupt, &msg);
|
||||||
|
if (!KSUCCESS(st)) goto failed;
|
||||||
|
st = PciBindMessage(pdo, &requests[i], 1u, cap, offset + 16u * i);
|
||||||
|
if (!KSUCCESS(st)) goto failed;
|
||||||
|
volatile uint32_t* entry = (volatile uint32_t*)(mapped + offset + 16u * i);
|
||||||
|
entry[3] = 1u;
|
||||||
|
entry[0] = (uint32_t)msg.Address;
|
||||||
|
entry[1] = (uint32_t)(msg.Address >> 32);
|
||||||
|
entry[2] = msg.Data;
|
||||||
|
entry[3] = 0u;
|
||||||
|
// Read back the entry to drain posted MMIO writes before enabling MSI-X.
|
||||||
|
(void)entry[3];
|
||||||
|
}
|
||||||
|
PciRawWrite16(bus, dev, fn, cap + 2u, (control | 0x8000u) & ~0x4000u);
|
||||||
|
(void)PciRawRead16(bus, dev, fn, cap + 2u);
|
||||||
|
PciRawWrite16(bus, dev, fn, PCI_REG_COMMAND_STATUS, command | PCI_COMMAND_INTX_DISABLE);
|
||||||
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
st = KeInterruptActivateMessage(requests[i].Interrupt);
|
||||||
|
if (!KSUCCESS(st)) goto failed;
|
||||||
|
}
|
||||||
|
return NTLSTATUS_SUCCESS;
|
||||||
|
failed:
|
||||||
|
PciRawWrite16(bus, dev, fn, cap + 2u, control & ~0x8000u);
|
||||||
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
if (requests[i].Interrupt) {
|
||||||
|
KeInterruptDisconnect(requests[i].Interrupt);
|
||||||
|
requests[i].Interrupt = (KE_INTERRUPT*)0;
|
||||||
|
}
|
||||||
|
if (requests[i].BusContext) {
|
||||||
|
MmFreePool(requests[i].BusContext);
|
||||||
|
requests[i].BusContext = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
static KSTATUS PciConnectMsi(DEVICE_OBJECT* pdo, PCI_PDO_EXTENSION* ext,
|
||||||
|
PCI_INTERRUPT_REQUEST* request) {
|
||||||
|
uint8_t cap = PciFindCapability(ext, PCI_CAP_ID_MSI);
|
||||||
|
if (!cap) return NTLSTATUS_NOT_SUPPORTED;
|
||||||
|
uint8_t bus = ext->Info.Address.Bus, dev = ext->Info.Address.Device;
|
||||||
|
uint8_t fn = ext->Info.Address.Function;
|
||||||
|
KSTATUS st = KeInterruptReserveMessage(request->Affinity, request->Routine,
|
||||||
|
request->Context, &request->Interrupt);
|
||||||
|
if (!KSUCCESS(st)) return st;
|
||||||
|
NTL_DDK_MSI_MESSAGE msg;
|
||||||
|
st = KeInterruptComposeMessage(request->Interrupt, &msg);
|
||||||
|
if (!KSUCCESS(st)) goto failed;
|
||||||
|
st = PciBindMessage(pdo, request, 0u, cap, 0);
|
||||||
|
if (!KSUCCESS(st)) goto failed;
|
||||||
|
uint8_t msixCap = PciFindCapability(ext, PCI_CAP_ID_MSIX);
|
||||||
|
if (msixCap) {
|
||||||
|
uint16_t msixControl = PciRawRead16(bus, dev, fn, msixCap + 2u);
|
||||||
|
PciRawWrite16(bus, dev, fn, msixCap + 2u,
|
||||||
|
(msixControl | 0x4000u) & (uint16_t)~0x8000u);
|
||||||
|
}
|
||||||
|
uint16_t control = PciRawRead16(bus, dev, fn, cap + 2u);
|
||||||
|
bool is64 = (control & PCI_MSI_CTRL_64BIT) != 0;
|
||||||
|
bool pvm = (control & PCI_MSI_CTRL_PVM) != 0;
|
||||||
|
PciRawWrite32(bus, dev, fn, cap + 4u, (uint32_t)msg.Address);
|
||||||
|
if (is64) {
|
||||||
|
PciRawWrite32(bus, dev, fn, cap + 8u, (uint32_t)(msg.Address >> 32));
|
||||||
|
PciRawWrite16(bus, dev, fn, cap + 12u, (uint16_t)msg.Data);
|
||||||
|
if (pvm) PciRawWrite32(bus, dev, fn, cap + 16u, 0);
|
||||||
|
} else {
|
||||||
|
PciRawWrite16(bus, dev, fn, cap + 8u, (uint16_t)msg.Data);
|
||||||
|
if (pvm) PciRawWrite32(bus, dev, fn, cap + 12u, 0);
|
||||||
|
}
|
||||||
|
control = (control & ~(uint16_t)PCI_MSI_CTRL_MME_MASK) | PCI_MSI_CTRL_ENABLE;
|
||||||
|
PciRawWrite16(bus, dev, fn, cap + 2u, control);
|
||||||
|
uint16_t command = PciRawRead16(bus, dev, fn, PCI_REG_COMMAND_STATUS);
|
||||||
|
PciRawWrite16(bus, dev, fn, PCI_REG_COMMAND_STATUS, command | PCI_COMMAND_INTX_DISABLE);
|
||||||
|
st = KeInterruptActivateMessage(request->Interrupt);
|
||||||
|
if (!KSUCCESS(st)) goto failed;
|
||||||
|
return NTLSTATUS_SUCCESS;
|
||||||
|
failed:
|
||||||
|
{
|
||||||
|
uint16_t previous = PciRawRead16(bus, dev, fn, cap + 2u);
|
||||||
|
PciRawWrite16(bus, dev, fn, cap + 2u,
|
||||||
|
previous & (uint16_t)~PCI_MSI_CTRL_ENABLE);
|
||||||
|
}
|
||||||
|
KeInterruptDisconnect(request->Interrupt);
|
||||||
|
request->Interrupt = (KE_INTERRUPT*)0;
|
||||||
|
if (request->BusContext) {
|
||||||
|
MmFreePool(request->BusContext);
|
||||||
|
request->BusContext = 0;
|
||||||
|
}
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
__declspec(dllexport) KSTATUS PciConnectInterrupts(DEVICE_OBJECT* pdo,
|
||||||
|
PCI_INTERRUPT_REQUEST* requests, uint32_t count, bool* usingMessages) {
|
||||||
|
PCI_PDO_EXTENSION* ext;
|
||||||
|
if (!PciIsPdo(pdo, &ext) || !requests || !count || !usingMessages)
|
||||||
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
|
*usingMessages = false;
|
||||||
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
if (!requests[i].Routine) return NTLSTATUS_INVALID_PARAMETER;
|
||||||
|
requests[i].Interrupt = (KE_INTERRUPT*)0;
|
||||||
|
requests[i].BusContext = 0;
|
||||||
|
}
|
||||||
|
KSTATUS st = PciConnectMsix(pdo, ext, requests, count);
|
||||||
|
if (KSUCCESS(st)) { *usingMessages = true; return st; }
|
||||||
|
if (count > 1u) return st;
|
||||||
|
st = PciConnectMsi(pdo, ext, requests);
|
||||||
|
if (KSUCCESS(st)) { *usingMessages = true; return st; }
|
||||||
|
uint8_t line = ext->Info.InterruptLine;
|
||||||
|
uint8_t pin = ext->Info.InterruptPin;
|
||||||
|
if (pin < 1u || pin > 4u || line == 0u || line == 0xFFu) {
|
||||||
|
DbgPrint("pci: INTx resource unavailable for %02x:%02x.%u pin=%u line=%u\n",
|
||||||
|
ext->Info.Address.Bus, ext->Info.Address.Device,
|
||||||
|
ext->Info.Address.Function, pin, line);
|
||||||
|
return NTLSTATUS_NOT_FOUND;
|
||||||
|
}
|
||||||
|
// The Interrupt Line register is a firmware hint until PCI _PRT routing is available.
|
||||||
|
DbgPrint("pci: INTx legacy route %02x:%02x.%u pin=%u line=%u\n",
|
||||||
|
ext->Info.Address.Bus, ext->Info.Address.Device,
|
||||||
|
ext->Info.Address.Function, pin, line);
|
||||||
|
if (line < 16u)
|
||||||
|
st = KeInterruptConnectIsa(line, 0x0Fu, requests[0].Affinity,
|
||||||
|
requests[0].Routine, requests[0].Context, &requests[0].Interrupt);
|
||||||
|
else
|
||||||
|
st = KeInterruptConnectGsi(line, 0x0Fu, requests[0].Affinity,
|
||||||
|
requests[0].Routine, requests[0].Context, &requests[0].Interrupt);
|
||||||
|
if (KSUCCESS(st)) {
|
||||||
|
uint16_t command = PciRawRead16(ext->Info.Address.Bus,
|
||||||
|
ext->Info.Address.Device, ext->Info.Address.Function, PCI_REG_COMMAND_STATUS);
|
||||||
|
PciRawWrite16(ext->Info.Address.Bus, ext->Info.Address.Device,
|
||||||
|
ext->Info.Address.Function, PCI_REG_COMMAND_STATUS,
|
||||||
|
command & (uint16_t)~PCI_COMMAND_INTX_DISABLE);
|
||||||
|
}
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
__declspec(dllexport) void PciDisconnectInterrupts(DEVICE_OBJECT* pdo,
|
||||||
|
PCI_INTERRUPT_REQUEST* requests, uint32_t count) {
|
||||||
|
PCI_PDO_EXTENSION* ext;
|
||||||
|
if (!PciIsPdo(pdo, &ext) || !requests) return;
|
||||||
|
// Close every route before disabling PCI delivery so an affinity update
|
||||||
|
// cannot resume the device after its disconnect has begun.
|
||||||
|
for (uint32_t i = 0; i < count; i++)
|
||||||
|
if (requests[i].Interrupt) KeInterruptBeginDisconnect(requests[i].Interrupt);
|
||||||
|
uint8_t bus = ext->Info.Address.Bus, dev = ext->Info.Address.Device;
|
||||||
|
uint8_t fn = ext->Info.Address.Function;
|
||||||
|
uint8_t msi = PciFindCapability(ext, PCI_CAP_ID_MSI);
|
||||||
|
uint8_t msix = PciFindCapability(ext, PCI_CAP_ID_MSIX);
|
||||||
|
if (msi) {
|
||||||
|
uint16_t control = PciRawRead16(bus, dev, fn, msi + 2u);
|
||||||
|
PciRawWrite16(bus, dev, fn, msi + 2u, control & ~PCI_MSI_CTRL_ENABLE);
|
||||||
|
}
|
||||||
|
if (msix) {
|
||||||
|
uint16_t control = PciRawRead16(bus, dev, fn, msix + 2u);
|
||||||
|
PciRawWrite16(bus, dev, fn, msix + 2u, (control | 0x4000u) & ~0x8000u);
|
||||||
|
}
|
||||||
|
uint16_t command = PciRawRead16(bus, dev, fn, PCI_REG_COMMAND_STATUS);
|
||||||
|
PciRawWrite16(bus, dev, fn, PCI_REG_COMMAND_STATUS, command | PCI_COMMAND_INTX_DISABLE);
|
||||||
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
if (requests[i].Interrupt) {
|
||||||
|
KeInterruptDisconnect(requests[i].Interrupt);
|
||||||
|
requests[i].Interrupt = (KE_INTERRUPT*)0;
|
||||||
|
}
|
||||||
|
if (requests[i].BusContext) {
|
||||||
|
MmFreePool(requests[i].BusContext);
|
||||||
|
requests[i].BusContext = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
||||||
(void)module;
|
(void)module;
|
||||||
|
|
||||||
|
|||||||
@@ -37,10 +37,13 @@
|
|||||||
#define PCI_MSI_CTRL_64BIT 0x0080u
|
#define PCI_MSI_CTRL_64BIT 0x0080u
|
||||||
#define PCI_MSI_CTRL_PVM 0x0100u
|
#define PCI_MSI_CTRL_PVM 0x0100u
|
||||||
|
|
||||||
#define PCI_IRQ_VECTOR_BASE 0x20u
|
|
||||||
|
|
||||||
typedef struct PCI_PDO_EXTENSION {
|
typedef struct PCI_PDO_EXTENSION {
|
||||||
PCI_DEVICE_INFO Info;
|
PCI_DEVICE_INFO Info;
|
||||||
PCI_BAR Bars[PCI_MAX_BARS];
|
PCI_BAR Bars[PCI_MAX_BARS];
|
||||||
uint8_t CapabilityOffset;
|
uint8_t CapabilityOffset;
|
||||||
|
// The MSI-X table is mapped once for the lifetime of its PCI PDO.
|
||||||
|
volatile uint8_t* MsixTable;
|
||||||
|
uint64_t MsixMappedLength;
|
||||||
|
uint8_t MsixBarIndex;
|
||||||
} PCI_PDO_EXTENSION;
|
} PCI_PDO_EXTENSION;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
TARGETNAME=pci
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=DRIVER
|
||||||
|
FLAVOR=DRIVER
|
||||||
|
EXTRA_CFLAGS=/DPCI_SYS_BUILD
|
||||||
|
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\ntlddk.lib" "$(BASEDIR)\bin\printf.lib"
|
||||||
|
EXTRA_LFLAGS=/NOENTRY /IMPLIB:"$(BASEDIR)\bin\pci.lib"
|
||||||
|
SOURCES=@/code/drivers/bus/pci/pci.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!include $(BASEDIR)\makefile.def
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
TARGETNAME=usb
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=DRIVER
|
||||||
|
FLAVOR=DRIVER
|
||||||
|
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\pci.lib"
|
||||||
|
EXTRA_LFLAGS=/NOENTRY
|
||||||
|
SOURCES=@/code/drivers/bus/usb/usb.c @/code/drivers/bus/usb/usb_bus.c @/code/drivers/bus/usb/usb_composite.c @/code/drivers/bus/usb/usb_core.c @/code/drivers/bus/usb/usb_xhci.c @/code/drivers/bus/usb/usb_hid.c \
|
||||||
|
@/code/drivers/bus/usb/usb_storage.c @/code/drivers/bus/usb/usb_hub.c
|
||||||
@@ -29,7 +29,6 @@
|
|||||||
#if USB_DEBUG_VERBOSE
|
#if USB_DEBUG_VERBOSE
|
||||||
#define UsbTrace DbgPrint
|
#define UsbTrace DbgPrint
|
||||||
#else
|
#else
|
||||||
// Implements the trace operation.
|
|
||||||
static __inline void UsbTrace(const char* fmt, ...) { (void)fmt; }
|
static __inline void UsbTrace(const char* fmt, ...) { (void)fmt; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -802,7 +801,7 @@ typedef struct XHCI_CONTROLLER {
|
|||||||
uint8_t Bus;
|
uint8_t Bus;
|
||||||
uint8_t Dev;
|
uint8_t Dev;
|
||||||
uint8_t Fn;
|
uint8_t Fn;
|
||||||
uint8_t Irq;
|
PCI_INTERRUPT_REQUEST InterruptRequest;
|
||||||
bool UsingMsi;
|
bool UsingMsi;
|
||||||
|
|
||||||
uint64_t MmioPhys;
|
uint64_t MmioPhys;
|
||||||
@@ -962,7 +961,7 @@ void XhciUnregisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target);
|
|||||||
KSTATUS XhciWaitForArmedTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target, uint32_t timeoutUs);
|
KSTATUS XhciWaitForArmedTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target, uint32_t timeoutUs);
|
||||||
KSTATUS XhciWaitForTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target, uint32_t timeoutUs);
|
KSTATUS XhciWaitForTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target, uint32_t timeoutUs);
|
||||||
void XhciEventDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2);
|
void XhciEventDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2);
|
||||||
void XhciIsr(void);
|
void XhciIsr(void* context);
|
||||||
KSTATUS XhciBiosHandoff(XHCI_CONTROLLER* xhci);
|
KSTATUS XhciBiosHandoff(XHCI_CONTROLLER* xhci);
|
||||||
KSTATUS XhciStopAndReset(XHCI_CONTROLLER* xhci);
|
KSTATUS XhciStopAndReset(XHCI_CONTROLLER* xhci);
|
||||||
KSTATUS XhciAllocateScratchpads(XHCI_CONTROLLER* xhci);
|
KSTATUS XhciAllocateScratchpads(XHCI_CONTROLLER* xhci);
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ DRIVER_OBJECT gUsbBusDriver;
|
|||||||
static bool gUsbBusModelReady;
|
static bool gUsbBusModelReady;
|
||||||
static uint8_t gUsbNextControllerIndex;
|
static uint8_t gUsbNextControllerIndex;
|
||||||
|
|
||||||
// Implements the device Destroy operation.
|
|
||||||
static void UsbDeviceDestroy(OBJECT* object) {
|
static void UsbDeviceDestroy(OBJECT* object) {
|
||||||
USB_DEVICE* dev = (USB_DEVICE*)object;
|
USB_DEVICE* dev = (USB_DEVICE*)object;
|
||||||
if (dev->RemoveLockReady) {
|
if (dev->RemoveLockReady) {
|
||||||
@@ -36,22 +35,18 @@ static void UsbPipeDestroy(OBJECT* object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the reference Device operation.
|
|
||||||
void UsbReferenceDevice(USB_DEVICE* dev) {
|
void UsbReferenceDevice(USB_DEVICE* dev) {
|
||||||
if (dev) ObReferenceObject(&dev->Header);
|
if (dev) ObReferenceObject(&dev->Header);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the dereference Device operation.
|
|
||||||
void UsbDereferenceDevice(USB_DEVICE* dev) {
|
void UsbDereferenceDevice(USB_DEVICE* dev) {
|
||||||
if (dev) ObDereferenceObject(&dev->Header);
|
if (dev) ObDereferenceObject(&dev->Header);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the reference Pipe operation.
|
|
||||||
void UsbReferencePipe(USB_PIPE* pipe) {
|
void UsbReferencePipe(USB_PIPE* pipe) {
|
||||||
if (pipe) ObReferenceObject(&pipe->Header);
|
if (pipe) ObReferenceObject(&pipe->Header);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the dereference Pipe operation.
|
|
||||||
void UsbDereferencePipe(USB_PIPE* pipe) {
|
void UsbDereferencePipe(USB_PIPE* pipe) {
|
||||||
if (pipe) ObDereferenceObject(&pipe->Header);
|
if (pipe) ObDereferenceObject(&pipe->Header);
|
||||||
}
|
}
|
||||||
@@ -111,12 +106,10 @@ KSTATUS UsbCreatePipe(USB_DEVICE* dev,
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the id From Buffer operation.
|
|
||||||
static SYS_STRING_VIEW UsbIdFromBuffer(char* buf) {
|
static SYS_STRING_VIEW UsbIdFromBuffer(char* buf) {
|
||||||
return SysSvFromCstr(buf);
|
return SysSvFromCstr(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the id Put Char operation.
|
|
||||||
static void UsbIdPutChar(char* buf, size_t cap, size_t* pos, char ch) {
|
static void UsbIdPutChar(char* buf, size_t cap, size_t* pos, char ch) {
|
||||||
if (!buf || !pos || cap == 0)
|
if (!buf || !pos || cap == 0)
|
||||||
return;
|
return;
|
||||||
@@ -129,7 +122,6 @@ static void UsbIdPutChar(char* buf, size_t cap, size_t* pos, char ch) {
|
|||||||
buf[cap - 1] = '\0';
|
buf[cap - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the id Append Literal operation.
|
|
||||||
static void UsbIdAppendLiteral(char* buf, size_t cap, size_t* pos, const char* text) {
|
static void UsbIdAppendLiteral(char* buf, size_t cap, size_t* pos, const char* text) {
|
||||||
if (!text)
|
if (!text)
|
||||||
return;
|
return;
|
||||||
@@ -137,7 +129,6 @@ static void UsbIdAppendLiteral(char* buf, size_t cap, size_t* pos, const char* t
|
|||||||
UsbIdPutChar(buf, cap, pos, *text++);
|
UsbIdPutChar(buf, cap, pos, *text++);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the id Append Hex operation.
|
|
||||||
static void UsbIdAppendHex(char* buf, size_t cap, size_t* pos, uint32_t value, uint8_t digits) {
|
static void UsbIdAppendHex(char* buf, size_t cap, size_t* pos, uint32_t value, uint8_t digits) {
|
||||||
static const char kHex[] = "0123456789ABCDEF";
|
static const char kHex[] = "0123456789ABCDEF";
|
||||||
while (digits) {
|
while (digits) {
|
||||||
@@ -146,7 +137,6 @@ static void UsbIdAppendHex(char* buf, size_t cap, size_t* pos, uint32_t value, u
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the format Vid Pid Rev operation.
|
|
||||||
static void UsbFormatVidPidRev(char* buf, size_t cap, uint16_t vid, uint16_t pid, uint16_t rev) {
|
static void UsbFormatVidPidRev(char* buf, size_t cap, uint16_t vid, uint16_t pid, uint16_t rev) {
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
if (cap) buf[0] = '\0';
|
if (cap) buf[0] = '\0';
|
||||||
@@ -158,7 +148,6 @@ static void UsbFormatVidPidRev(char* buf, size_t cap, uint16_t vid, uint16_t pid
|
|||||||
UsbIdAppendHex(buf, cap, &pos, rev, 4);
|
UsbIdAppendHex(buf, cap, &pos, rev, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the format Vid Pid operation.
|
|
||||||
static void UsbFormatVidPid(char* buf, size_t cap, uint16_t vid, uint16_t pid) {
|
static void UsbFormatVidPid(char* buf, size_t cap, uint16_t vid, uint16_t pid) {
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
if (cap) buf[0] = '\0';
|
if (cap) buf[0] = '\0';
|
||||||
@@ -168,7 +157,6 @@ static void UsbFormatVidPid(char* buf, size_t cap, uint16_t vid, uint16_t pid) {
|
|||||||
UsbIdAppendHex(buf, cap, &pos, pid, 4);
|
UsbIdAppendHex(buf, cap, &pos, pid, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the format Vid Pid Mi operation.
|
|
||||||
static void UsbFormatVidPidMi(char* buf, size_t cap, uint16_t vid, uint16_t pid, uint8_t mi) {
|
static void UsbFormatVidPidMi(char* buf, size_t cap, uint16_t vid, uint16_t pid, uint8_t mi) {
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
if (cap) buf[0] = '\0';
|
if (cap) buf[0] = '\0';
|
||||||
@@ -180,7 +168,6 @@ static void UsbFormatVidPidMi(char* buf, size_t cap, uint16_t vid, uint16_t pid,
|
|||||||
UsbIdAppendHex(buf, cap, &pos, mi, 2);
|
UsbIdAppendHex(buf, cap, &pos, mi, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the format Class Sub Prot operation.
|
|
||||||
static void UsbFormatClassSubProt(char* buf, size_t cap, uint8_t cls, uint8_t sub, uint8_t proto) {
|
static void UsbFormatClassSubProt(char* buf, size_t cap, uint8_t cls, uint8_t sub, uint8_t proto) {
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
if (cap) buf[0] = '\0';
|
if (cap) buf[0] = '\0';
|
||||||
@@ -192,7 +179,6 @@ static void UsbFormatClassSubProt(char* buf, size_t cap, uint8_t cls, uint8_t su
|
|||||||
UsbIdAppendHex(buf, cap, &pos, proto, 2);
|
UsbIdAppendHex(buf, cap, &pos, proto, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the format Class operation.
|
|
||||||
static void UsbFormatClass(char* buf, size_t cap, uint8_t cls) {
|
static void UsbFormatClass(char* buf, size_t cap, uint8_t cls) {
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
if (cap) buf[0] = '\0';
|
if (cap) buf[0] = '\0';
|
||||||
@@ -200,14 +186,12 @@ static void UsbFormatClass(char* buf, size_t cap, uint8_t cls) {
|
|||||||
UsbIdAppendHex(buf, cap, &pos, cls, 2);
|
UsbIdAppendHex(buf, cap, &pos, cls, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the format Composite operation.
|
|
||||||
static void UsbFormatComposite(char* buf, size_t cap) {
|
static void UsbFormatComposite(char* buf, size_t cap) {
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
if (cap) buf[0] = '\0';
|
if (cap) buf[0] = '\0';
|
||||||
UsbIdAppendLiteral(buf, cap, &pos, "USB\\COMPOSITE");
|
UsbIdAppendLiteral(buf, cap, &pos, "USB\\COMPOSITE");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the format Root Hub operation.
|
|
||||||
static void UsbFormatRootHub(char* buf, size_t cap) {
|
static void UsbFormatRootHub(char* buf, size_t cap) {
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
if (cap) buf[0] = '\0';
|
if (cap) buf[0] = '\0';
|
||||||
@@ -452,7 +436,6 @@ KSTATUS UsbCreateInterfacePdos(USB_HCD* hcd, XHCI_DEVICE* xdev, DEVICE_OBJECT* p
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the reference First Child operation.
|
|
||||||
static DEVICE_OBJECT* UsbReferenceFirstChild(DEVICE_OBJECT* parent) {
|
static DEVICE_OBJECT* UsbReferenceFirstChild(DEVICE_OBJECT* parent) {
|
||||||
if (!parent) return (DEVICE_OBJECT*)0;
|
if (!parent) return (DEVICE_OBJECT*)0;
|
||||||
uintptr_t flags = KeAcquireSpinlock(&parent->Lock);
|
uintptr_t flags = KeAcquireSpinlock(&parent->Lock);
|
||||||
@@ -463,7 +446,6 @@ static DEVICE_OBJECT* UsbReferenceFirstChild(DEVICE_OBJECT* parent) {
|
|||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the send Pnp If Alive operation.
|
|
||||||
static void UsbSendPnpIfAlive(DEVICE_OBJECT* pdo, IO_PNP_MINOR_FUNCTION minor) {
|
static void UsbSendPnpIfAlive(DEVICE_OBJECT* pdo, IO_PNP_MINOR_FUNCTION minor) {
|
||||||
if (!pdo || pdo->DeletePending)
|
if (!pdo || pdo->DeletePending)
|
||||||
return;
|
return;
|
||||||
@@ -550,7 +532,6 @@ KSTATUS UsbSubmitUrbSync(DEVICE_OBJECT* target, USB_URB* urb) {
|
|||||||
return KSUCCESS(st) ? urb->Status : st;
|
return KSUCCESS(st) ? urb->Status : st;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the async Urb Irp Complete operation.
|
|
||||||
static void UsbAsyncUrbIrpComplete(IRP* irp, void* context) {
|
static void UsbAsyncUrbIrpComplete(IRP* irp, void* context) {
|
||||||
(void)context;
|
(void)context;
|
||||||
IoFreeIrp(irp);
|
IoFreeIrp(irp);
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ static const IO_DRIVER_ID_TABLE gUsbCompositeIdTable = {
|
|||||||
sizeof(gUsbCompositeIds) / sizeof(gUsbCompositeIds[0]),
|
sizeof(gUsbCompositeIds) / sizeof(gUsbCompositeIds[0]),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements the composite Create Interfaces operation.
|
|
||||||
static KSTATUS UsbCompositeCreateInterfaces(USB_COMPOSITE_EXTENSION* ext) {
|
static KSTATUS UsbCompositeCreateInterfaces(USB_COMPOSITE_EXTENSION* ext) {
|
||||||
if (!ext || !ext->Device || ext->InterfacesCreated)
|
if (!ext || !ext->Device || ext->InterfacesCreated)
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
@@ -28,7 +27,6 @@ static KSTATUS UsbCompositeCreateInterfaces(USB_COMPOSITE_EXTENSION* ext) {
|
|||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the composite Forward Pnp operation.
|
|
||||||
static KSTATUS UsbCompositeForwardPnp(DEVICE_OBJECT* device, IRP* irp, KSTATUS localStatus) {
|
static KSTATUS UsbCompositeForwardPnp(DEVICE_OBJECT* device, IRP* irp, KSTATUS localStatus) {
|
||||||
if (!KSUCCESS(localStatus)) {
|
if (!KSUCCESS(localStatus)) {
|
||||||
IoCompleteRequest(irp, localStatus, 0);
|
IoCompleteRequest(irp, localStatus, 0);
|
||||||
@@ -37,7 +35,6 @@ static KSTATUS UsbCompositeForwardPnp(DEVICE_OBJECT* device, IRP* irp, KSTATUS l
|
|||||||
return IoForwardIrpToLower(device, irp);
|
return IoForwardIrpToLower(device, irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the composite Dispatch Pnp operation.
|
|
||||||
KSTATUS UsbCompositeDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
KSTATUS UsbCompositeDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
||||||
if (!device || !irp)
|
if (!device || !irp)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -114,7 +111,6 @@ KSTATUS UsbCompositeDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the composite Add Device operation.
|
|
||||||
KSTATUS UsbCompositeAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
KSTATUS UsbCompositeAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
||||||
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
|
|||||||
@@ -260,7 +260,6 @@ KSTATUS XhciDiscoverAndSetConfiguration(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev,
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the rollback Enumerated Slot operation.
|
|
||||||
static void XhciRollbackEnumeratedSlot(XHCI_CONTROLLER* xhci, uint8_t slotId) {
|
static void XhciRollbackEnumeratedSlot(XHCI_CONTROLLER* xhci, uint8_t slotId) {
|
||||||
if (!xhci || slotId == 0 || slotId > XHCI_MAX_TRACKED_SLOTS)
|
if (!xhci || slotId == 0 || slotId > XHCI_MAX_TRACKED_SLOTS)
|
||||||
return;
|
return;
|
||||||
@@ -399,7 +398,6 @@ static KSTATUS XhciEnumeratePathEx(XHCI_CONTROLLER* xhci,
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the enumerate Port Ex operation.
|
|
||||||
KSTATUS XhciEnumeratePortEx(XHCI_CONTROLLER* xhci, uint8_t port, uint8_t* outSlotId) {
|
KSTATUS XhciEnumeratePortEx(XHCI_CONTROLLER* xhci, uint8_t port, uint8_t* outSlotId) {
|
||||||
if (outSlotId) *outSlotId = 0;
|
if (outSlotId) *outSlotId = 0;
|
||||||
|
|
||||||
@@ -449,12 +447,10 @@ KSTATUS XhciEnumerateHubPortEx(XHCI_CONTROLLER* xhci,
|
|||||||
return XhciEnumeratePathEx(xhci, hubPort, speed, &path, hub->Self, outSlotId);
|
return XhciEnumeratePathEx(xhci, hubPort, speed, &path, hub->Self, outSlotId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the enumerate Port operation.
|
|
||||||
KSTATUS XhciEnumeratePort(XHCI_CONTROLLER* xhci, uint8_t port) {
|
KSTATUS XhciEnumeratePort(XHCI_CONTROLLER* xhci, uint8_t port) {
|
||||||
return XhciEnumeratePortEx(xhci, port, (uint8_t*)0);
|
return XhciEnumeratePortEx(xhci, port, (uint8_t*)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the enumerate Root Ports operation.
|
|
||||||
void XhciEnumerateRootPorts(XHCI_CONTROLLER* xhci) {
|
void XhciEnumerateRootPorts(XHCI_CONTROLLER* xhci) {
|
||||||
uint32_t attempted = 0;
|
uint32_t attempted = 0;
|
||||||
uint32_t configured = 0;
|
uint32_t configured = 0;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ static void UsbHidReleaseDma(USB_HID_EXTENSION* ext) {
|
|||||||
ext->ReportBufferDeviceAddress = 0;
|
ext->ReportBufferDeviceAddress = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hid Key In Report operation.
|
|
||||||
bool XhciHidKeyInReport(const uint8_t* keys, uint8_t key) {
|
bool XhciHidKeyInReport(const uint8_t* keys, uint8_t key) {
|
||||||
if (key == 0 || key == 1) return false;
|
if (key == 0 || key == 1) return false;
|
||||||
for (uint8_t i = 0; i < 6; i++) {
|
for (uint8_t i = 0; i < 6; i++) {
|
||||||
@@ -94,7 +93,6 @@ void XhciProcessBootMouseReport(XHCI_DEVICE* dev, const uint8_t* report, uint16_
|
|||||||
dev->HidLastButtons = buttons;
|
dev->HidLastButtons = buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the arm Hid Interrupt In operation.
|
|
||||||
KSTATUS XhciArmHidInterruptIn(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
KSTATUS XhciArmHidInterruptIn(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
||||||
if (!dev->HidActive || dev->HidArmed || !dev->HidRing || !dev->HidBuffer)
|
if (!dev->HidActive || dev->HidArmed || !dev->HidRing || !dev->HidBuffer)
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
@@ -122,7 +120,6 @@ KSTATUS XhciArmHidInterruptIn(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the arm All Hid operation.
|
|
||||||
void XhciArmAllHid(XHCI_CONTROLLER* xhci) {
|
void XhciArmAllHid(XHCI_CONTROLLER* xhci) {
|
||||||
for (uint8_t slot = 1; slot <= XHCI_MAX_TRACKED_SLOTS; slot++) {
|
for (uint8_t slot = 1; slot <= XHCI_MAX_TRACKED_SLOTS; slot++) {
|
||||||
XHCI_DEVICE* dev = &xhci->Devices[slot];
|
XHCI_DEVICE* dev = &xhci->Devices[slot];
|
||||||
@@ -241,7 +238,6 @@ KSTATUS XhciAllocateHidMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the configure Hid Endpoint operation.
|
|
||||||
KSTATUS XhciConfigureHidEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
KSTATUS XhciConfigureHidEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
||||||
if (!dev->HidCandidate)
|
if (!dev->HidCandidate)
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
@@ -328,7 +324,6 @@ static const IO_DRIVER_ID_TABLE gUsbHidIdTable = {
|
|||||||
sizeof(gUsbHidIds) / sizeof(gUsbHidIds[0]),
|
sizeof(gUsbHidIds) / sizeof(gUsbHidIds[0]),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements the hid Is Qemu Absolute Tablet Pdo operation.
|
|
||||||
static bool UsbHidIsQemuAbsoluteTabletPdo(const USB_PDO_EXTENSION* pdoExt, const USB_ENDPOINT_DESCRIPTOR* ep) {
|
static bool UsbHidIsQemuAbsoluteTabletPdo(const USB_PDO_EXTENSION* pdoExt, const USB_ENDPOINT_DESCRIPTOR* ep) {
|
||||||
if (!pdoExt || !pdoExt->Device || !ep)
|
if (!pdoExt || !pdoExt->Device || !ep)
|
||||||
return false;
|
return false;
|
||||||
@@ -347,7 +342,6 @@ static bool UsbHidIsQemuAbsoluteTabletPdo(const USB_PDO_EXTENSION* pdoExt, const
|
|||||||
return (ep->wMaxPacketSize & 0x07FFu) >= 6u;
|
return (ep->wMaxPacketSize & 0x07FFu) >= 6u;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hid Find Interrupt In Pdo operation.
|
|
||||||
static const USB_ENDPOINT_DESCRIPTOR* UsbHidFindInterruptInPdo(const USB_PDO_EXTENSION* ext) {
|
static const USB_ENDPOINT_DESCRIPTOR* UsbHidFindInterruptInPdo(const USB_PDO_EXTENSION* ext) {
|
||||||
if (!ext) return (const USB_ENDPOINT_DESCRIPTOR*)0;
|
if (!ext) return (const USB_ENDPOINT_DESCRIPTOR*)0;
|
||||||
|
|
||||||
@@ -361,7 +355,6 @@ static const USB_ENDPOINT_DESCRIPTOR* UsbHidFindInterruptInPdo(const USB_PDO_EXT
|
|||||||
return (const USB_ENDPOINT_DESCRIPTOR*)0;
|
return (const USB_ENDPOINT_DESCRIPTOR*)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hid Process Boot Keyboard Report operation.
|
|
||||||
static void UsbHidProcessBootKeyboardReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) {
|
static void UsbHidProcessBootKeyboardReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) {
|
||||||
if (!ext || len < 8) return;
|
if (!ext || len < 8) return;
|
||||||
|
|
||||||
@@ -390,7 +383,6 @@ static void UsbHidProcessBootKeyboardReport(USB_HID_EXTENSION* ext, const uint8_
|
|||||||
memcpy(ext->LastKeys, keys, sizeof(ext->LastKeys));
|
memcpy(ext->LastKeys, keys, sizeof(ext->LastKeys));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hid Process Boot Mouse Report operation.
|
|
||||||
static void UsbHidProcessBootMouseReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) {
|
static void UsbHidProcessBootMouseReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) {
|
||||||
if (!ext || len < 3) return;
|
if (!ext || len < 3) return;
|
||||||
|
|
||||||
@@ -411,7 +403,6 @@ static void UsbHidProcessBootMouseReport(USB_HID_EXTENSION* ext, const uint8_t*
|
|||||||
ext->LastButtons = buttons;
|
ext->LastButtons = buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hid Process Qemu Tablet Report operation.
|
|
||||||
static void UsbHidProcessQemuTabletReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) {
|
static void UsbHidProcessQemuTabletReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) {
|
||||||
if (!ext || len < 5) return;
|
if (!ext || len < 5) return;
|
||||||
|
|
||||||
@@ -432,7 +423,6 @@ static void UsbHidProcessQemuTabletReport(USB_HID_EXTENSION* ext, const uint8_t*
|
|||||||
|
|
||||||
static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext);
|
static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext);
|
||||||
|
|
||||||
// Implements the hid Interrupt Complete operation.
|
|
||||||
static void UsbHidInterruptComplete(USB_URB* urb, void* context) {
|
static void UsbHidInterruptComplete(USB_URB* urb, void* context) {
|
||||||
USB_HID_EXTENSION* ext = (USB_HID_EXTENSION*)context;
|
USB_HID_EXTENSION* ext = (USB_HID_EXTENSION*)context;
|
||||||
if (!ext || urb != &ext->InterruptUrb)
|
if (!ext || urb != &ext->InterruptUrb)
|
||||||
@@ -470,7 +460,6 @@ static void UsbHidInterruptComplete(USB_URB* urb, void* context) {
|
|||||||
IoReleaseRemoveLock(&ext->RemoveLock, (IRP*)0);
|
IoReleaseRemoveLock(&ext->RemoveLock, (IRP*)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hid Send Boot Protocol operation.
|
|
||||||
static KSTATUS UsbHidSendBootProtocol(USB_HID_EXTENSION* ext) {
|
static KSTATUS UsbHidSendBootProtocol(USB_HID_EXTENSION* ext) {
|
||||||
if (!ext || !ext->LowerDevice || !ext->Device)
|
if (!ext || !ext->LowerDevice || !ext->Device)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -514,7 +503,6 @@ static KSTATUS UsbHidSendBootProtocol(USB_HID_EXTENSION* ext) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hid Arm Interrupt operation.
|
|
||||||
static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext) {
|
static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext) {
|
||||||
if (!ext || !ext->Started || ext->SurpriseRemoved || ext->Removed)
|
if (!ext || !ext->Started || ext->SurpriseRemoved || ext->Removed)
|
||||||
return NTLSTATUS_OBJECT_DEAD;
|
return NTLSTATUS_OBJECT_DEAD;
|
||||||
@@ -551,7 +539,6 @@ static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hid Start Device operation.
|
|
||||||
static KSTATUS UsbHidStartDevice(DEVICE_OBJECT* device, USB_HID_EXTENSION* ext) {
|
static KSTATUS UsbHidStartDevice(DEVICE_OBJECT* device, USB_HID_EXTENSION* ext) {
|
||||||
if (!device || !ext || !ext->Device || !ext->InterfacePdo)
|
if (!device || !ext || !ext->Device || !ext->InterfacePdo)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -660,7 +647,6 @@ static KSTATUS UsbHidStartDevice(DEVICE_OBJECT* device, USB_HID_EXTENSION* ext)
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hid Dispatch Pnp operation.
|
|
||||||
KSTATUS UsbHidDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
KSTATUS UsbHidDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
||||||
if (!device || !irp)
|
if (!device || !irp)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -758,7 +744,6 @@ KSTATUS UsbHidDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hid Add Device operation.
|
|
||||||
KSTATUS UsbHidAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
KSTATUS UsbHidAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
||||||
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
|
|||||||
@@ -31,19 +31,16 @@ static const IO_DRIVER_ID_TABLE gUsbHubIdTable = {
|
|||||||
#define USB_HUB_PORT_ENUMERATING 0xffu
|
#define USB_HUB_PORT_ENUMERATING 0xffu
|
||||||
#define USB_HUB_PORT_FAILED 0xfeu
|
#define USB_HUB_PORT_FAILED 0xfeu
|
||||||
|
|
||||||
// Implements the hub Slot Busy operation.
|
|
||||||
static bool UsbHubSlotBusy(uint8_t slot) {
|
static bool UsbHubSlotBusy(uint8_t slot) {
|
||||||
return slot != 0 && slot != USB_HUB_PORT_ENUMERATING && slot != USB_HUB_PORT_FAILED;
|
return slot != 0 && slot != USB_HUB_PORT_ENUMERATING && slot != USB_HUB_PORT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Root Port Connected operation.
|
|
||||||
static bool UsbHubRootPortConnected(XHCI_CONTROLLER* xhci, uint8_t port) {
|
static bool UsbHubRootPortConnected(XHCI_CONTROLLER* xhci, uint8_t port) {
|
||||||
if (!xhci || !xhci->Op || port == 0) return false;
|
if (!xhci || !xhci->Op || port == 0) return false;
|
||||||
uint32_t portsc = XhciRead32(xhci->Op, XhciPortReg(port));
|
uint32_t portsc = XhciRead32(xhci->Op, XhciPortReg(port));
|
||||||
return (portsc & XHCI_PORTSC_CCS) != 0;
|
return (portsc & XHCI_PORTSC_CCS) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Clear Root Port Failure operation.
|
|
||||||
static void UsbHubClearRootPortFailure(USB_HUB_EXTENSION* hub, uint8_t port) {
|
static void UsbHubClearRootPortFailure(USB_HUB_EXTENSION* hub, uint8_t port) {
|
||||||
if (!hub || port == 0 || port > USB_ROOT_HUB_MAX_PORTS) return;
|
if (!hub || port == 0 || port > USB_ROOT_HUB_MAX_PORTS) return;
|
||||||
hub->RootPortFailCount[port] = 0;
|
hub->RootPortFailCount[port] = 0;
|
||||||
@@ -51,7 +48,6 @@ static void UsbHubClearRootPortFailure(USB_HUB_EXTENSION* hub, uint8_t port) {
|
|||||||
hub->RootPortSlot[port] = 0;
|
hub->RootPortSlot[port] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Mark Root Port Failed operation.
|
|
||||||
static void UsbHubMarkRootPortFailed(USB_HUB_EXTENSION* hub, uint8_t port) {
|
static void UsbHubMarkRootPortFailed(USB_HUB_EXTENSION* hub, uint8_t port) {
|
||||||
if (!hub || port == 0 || port > USB_ROOT_HUB_MAX_PORTS) return;
|
if (!hub || port == 0 || port > USB_ROOT_HUB_MAX_PORTS) return;
|
||||||
hub->RootPortSlot[port] = USB_HUB_PORT_FAILED;
|
hub->RootPortSlot[port] = USB_HUB_PORT_FAILED;
|
||||||
@@ -146,7 +142,6 @@ static KSTATUS UsbHubEnumerateConnectedRootPort(USB_HUB_EXTENSION* hub,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Pop Pending Root Port operation.
|
|
||||||
static bool UsbHubPopPendingRootPort(USB_HUB_EXTENSION* hub, uint8_t* outPort) {
|
static bool UsbHubPopPendingRootPort(USB_HUB_EXTENSION* hub, uint8_t* outPort) {
|
||||||
if (!hub || !outPort) return false;
|
if (!hub || !outPort) return false;
|
||||||
|
|
||||||
@@ -168,7 +163,6 @@ static bool UsbHubPopPendingRootPort(USB_HUB_EXTENSION* hub, uint8_t* outPort) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Pop Pending External Port operation.
|
|
||||||
static bool UsbHubPopPendingExternalPort(USB_HUB_EXTENSION* hub, uint8_t* outPort) {
|
static bool UsbHubPopPendingExternalPort(USB_HUB_EXTENSION* hub, uint8_t* outPort) {
|
||||||
if (!hub || !outPort) return false;
|
if (!hub || !outPort) return false;
|
||||||
|
|
||||||
@@ -193,7 +187,6 @@ static bool UsbHubPopPendingExternalPort(USB_HUB_EXTENSION* hub, uint8_t* outPor
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Record Root Port Change operation.
|
|
||||||
static void UsbHubRecordRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
|
static void UsbHubRecordRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
|
||||||
if (!hub || port == 0 || port > hub->PortCount)
|
if (!hub || port == 0 || port > hub->PortCount)
|
||||||
return;
|
return;
|
||||||
@@ -206,7 +199,6 @@ static void UsbHubRecordRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
|
|||||||
KeSignalSemaphore(hub->WorkerSemaphore);
|
KeSignalSemaphore(hub->WorkerSemaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Queue External Port Change operation.
|
|
||||||
void UsbHubQueueExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
|
void UsbHubQueueExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
|
||||||
if (!hub || port == 0 || port > hub->PortCount || port > USB_EXTERNAL_HUB_MAX_PORTS)
|
if (!hub || port == 0 || port > hub->PortCount || port > USB_EXTERNAL_HUB_MAX_PORTS)
|
||||||
return;
|
return;
|
||||||
@@ -217,7 +209,6 @@ void UsbHubQueueExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
|
|||||||
KeSignalSemaphore(hub->WorkerSemaphore);
|
KeSignalSemaphore(hub->WorkerSemaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Remove Slot Child operation.
|
|
||||||
static void UsbHubRemoveSlotChild(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t slot) {
|
static void UsbHubRemoveSlotChild(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t slot) {
|
||||||
if (!hub || !hub->Hcd || slot == 0)
|
if (!hub || !hub->Hcd || slot == 0)
|
||||||
return;
|
return;
|
||||||
@@ -253,7 +244,6 @@ static void UsbHubRemoveSlotChild(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Remove Root Child operation.
|
|
||||||
static void UsbHubRemoveRootChild(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t slot) {
|
static void UsbHubRemoveRootChild(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t slot) {
|
||||||
UsbHubRemoveSlotChild(hub, port, slot);
|
UsbHubRemoveSlotChild(hub, port, slot);
|
||||||
}
|
}
|
||||||
@@ -306,7 +296,6 @@ static KSTATUS UsbHubControlNoData(USB_HUB_EXTENSION* hub,
|
|||||||
return UsbSubmitUrbSync(hub->LowerDevice, &urb);
|
return UsbSubmitUrbSync(hub->LowerDevice, &urb);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Read Descriptor operation.
|
|
||||||
static KSTATUS UsbHubReadDescriptor(USB_HUB_EXTENSION* hub, USB_HUB_DESCRIPTOR* outDesc) {
|
static KSTATUS UsbHubReadDescriptor(USB_HUB_EXTENSION* hub, USB_HUB_DESCRIPTOR* outDesc) {
|
||||||
if (!hub || !outDesc || !hub->ChangeBitmap || !hub->ChangeBitmapDeviceAddress)
|
if (!hub || !outDesc || !hub->ChangeBitmap || !hub->ChangeBitmapDeviceAddress)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -329,7 +318,6 @@ static KSTATUS UsbHubReadDescriptor(USB_HUB_EXTENSION* hub, USB_HUB_DESCRIPTOR*
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Get Port Status operation.
|
|
||||||
static KSTATUS UsbHubGetPortStatus(USB_HUB_EXTENSION* hub, uint8_t port, USB_HUB_PORT_STATUS* outStatus) {
|
static KSTATUS UsbHubGetPortStatus(USB_HUB_EXTENSION* hub, uint8_t port, USB_HUB_PORT_STATUS* outStatus) {
|
||||||
if (!hub || !outStatus || port == 0)
|
if (!hub || !outStatus || port == 0)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -350,7 +338,6 @@ static KSTATUS UsbHubGetPortStatus(USB_HUB_EXTENSION* hub, uint8_t port, USB_HUB
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Set Port Feature operation.
|
|
||||||
static KSTATUS UsbHubSetPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint16_t feature) {
|
static KSTATUS UsbHubSetPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint16_t feature) {
|
||||||
return UsbHubControlNoData(hub,
|
return UsbHubControlNoData(hub,
|
||||||
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER,
|
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER,
|
||||||
@@ -359,7 +346,6 @@ static KSTATUS UsbHubSetPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint16
|
|||||||
port);
|
port);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Clear Port Feature operation.
|
|
||||||
static KSTATUS UsbHubClearPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint16_t feature) {
|
static KSTATUS UsbHubClearPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint16_t feature) {
|
||||||
return UsbHubControlNoData(hub,
|
return UsbHubControlNoData(hub,
|
||||||
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER,
|
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER,
|
||||||
@@ -368,7 +354,6 @@ static KSTATUS UsbHubClearPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint
|
|||||||
port);
|
port);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Speed From Port Status operation.
|
|
||||||
static uint8_t UsbHubSpeedFromPortStatus(uint16_t status) {
|
static uint8_t UsbHubSpeedFromPortStatus(uint16_t status) {
|
||||||
if (status & USB_HUB_PORT_STATUS_LOW_SPEED)
|
if (status & USB_HUB_PORT_STATUS_LOW_SPEED)
|
||||||
return 2u;
|
return 2u;
|
||||||
@@ -377,7 +362,6 @@ static uint8_t UsbHubSpeedFromPortStatus(uint16_t status) {
|
|||||||
return 1u;
|
return 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Reset External Port operation.
|
|
||||||
static KSTATUS UsbHubResetExternalPort(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t* outSpeed) {
|
static KSTATUS UsbHubResetExternalPort(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t* outSpeed) {
|
||||||
if (outSpeed) *outSpeed = 0;
|
if (outSpeed) *outSpeed = 0;
|
||||||
if (!hub || port == 0)
|
if (!hub || port == 0)
|
||||||
@@ -426,7 +410,6 @@ static KSTATUS UsbHubResetExternalPort(USB_HUB_EXTENSION* hub, uint8_t port, uin
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Handle External Port Change operation.
|
|
||||||
static void UsbHubHandleExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
|
static void UsbHubHandleExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
|
||||||
if (!hub || hub->Kind != UsbHubKindExternal || port == 0 || port > hub->PortCount || port > USB_EXTERNAL_HUB_MAX_PORTS)
|
if (!hub || hub->Kind != UsbHubKindExternal || port == 0 || port > hub->PortCount || port > USB_EXTERNAL_HUB_MAX_PORTS)
|
||||||
return;
|
return;
|
||||||
@@ -509,7 +492,6 @@ static void UsbHubHandleExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Handle Root Port Change operation.
|
|
||||||
static void UsbHubHandleRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
|
static void UsbHubHandleRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
|
||||||
if (!hub || !hub->Hcd || port == 0 || port > hub->PortCount || port > USB_ROOT_HUB_MAX_PORTS)
|
if (!hub || !hub->Hcd || port == 0 || port > hub->PortCount || port > USB_ROOT_HUB_MAX_PORTS)
|
||||||
return;
|
return;
|
||||||
@@ -575,7 +557,6 @@ static void UsbHubHandleRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) {
|
|||||||
static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub);
|
static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub);
|
||||||
static KSTATUS UsbHubDoRootPortScan(USB_HCD* hcd);
|
static KSTATUS UsbHubDoRootPortScan(USB_HCD* hcd);
|
||||||
|
|
||||||
// Implements the hub Take Initial Root Scan operation.
|
|
||||||
static bool UsbHubTakeInitialRootScan(USB_HUB_EXTENSION* hub) {
|
static bool UsbHubTakeInitialRootScan(USB_HUB_EXTENSION* hub) {
|
||||||
if (!hub || hub->Kind != UsbHubKindRoot)
|
if (!hub || hub->Kind != UsbHubKindRoot)
|
||||||
return false;
|
return false;
|
||||||
@@ -589,7 +570,6 @@ static bool UsbHubTakeInitialRootScan(USB_HUB_EXTENSION* hub) {
|
|||||||
return take;
|
return take;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Worker operation.
|
|
||||||
static void UsbHubWorker(void* arg) {
|
static void UsbHubWorker(void* arg) {
|
||||||
USB_HUB_EXTENSION* hub = (USB_HUB_EXTENSION*)arg;
|
USB_HUB_EXTENSION* hub = (USB_HUB_EXTENSION*)arg;
|
||||||
if (hub && hub->Kind == UsbHubKindRoot && hub->Hcd) {
|
if (hub && hub->Kind == UsbHubKindRoot && hub->Hcd) {
|
||||||
@@ -687,7 +667,6 @@ static KSTATUS UsbHubStartWorker(USB_HUB_EXTENSION* hub) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Do Root Port Scan operation.
|
|
||||||
static KSTATUS UsbHubDoRootPortScan(USB_HCD* hcd) {
|
static KSTATUS UsbHubDoRootPortScan(USB_HCD* hcd) {
|
||||||
if (!hcd || !hcd->RootHubContext)
|
if (!hcd || !hcd->RootHubContext)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -774,7 +753,6 @@ KSTATUS UsbHubScheduleRootScan(USB_HCD* hcd) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Queue Root Port Change operation.
|
|
||||||
void UsbHubQueueRootPortChange(USB_HCD* hcd, uint8_t port) {
|
void UsbHubQueueRootPortChange(USB_HCD* hcd, uint8_t port) {
|
||||||
if (!hcd || !hcd->RootHubContext)
|
if (!hcd || !hcd->RootHubContext)
|
||||||
return;
|
return;
|
||||||
@@ -782,7 +760,6 @@ void UsbHubQueueRootPortChange(USB_HCD* hcd, uint8_t port) {
|
|||||||
UsbHubRecordRootPortChange(hub, port);
|
UsbHubRecordRootPortChange(hub, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Scan External Ports operation.
|
|
||||||
static KSTATUS UsbHubScanExternalPorts(USB_HUB_EXTENSION* hub) {
|
static KSTATUS UsbHubScanExternalPorts(USB_HUB_EXTENSION* hub) {
|
||||||
if (!hub || hub->Kind != UsbHubKindExternal)
|
if (!hub || hub->Kind != UsbHubKindExternal)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -810,7 +787,6 @@ static KSTATUS UsbHubScanExternalPorts(USB_HUB_EXTENSION* hub) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Find Interrupt In operation.
|
|
||||||
static const USB_ENDPOINT_DESCRIPTOR* UsbHubFindInterruptIn(USB_PDO_EXTENSION* pdoExt) {
|
static const USB_ENDPOINT_DESCRIPTOR* UsbHubFindInterruptIn(USB_PDO_EXTENSION* pdoExt) {
|
||||||
if (!pdoExt)
|
if (!pdoExt)
|
||||||
return (const USB_ENDPOINT_DESCRIPTOR*)0;
|
return (const USB_ENDPOINT_DESCRIPTOR*)0;
|
||||||
@@ -844,7 +820,6 @@ static const USB_ENDPOINT_DESCRIPTOR* UsbHubFindInterruptIn(USB_PDO_EXTENSION* p
|
|||||||
return (const USB_ENDPOINT_DESCRIPTOR*)0;
|
return (const USB_ENDPOINT_DESCRIPTOR*)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub External Change Complete operation.
|
|
||||||
static void UsbHubExternalChangeComplete(USB_URB* urb, void* context) {
|
static void UsbHubExternalChangeComplete(USB_URB* urb, void* context) {
|
||||||
USB_HUB_EXTENSION* hub = (USB_HUB_EXTENSION*)context;
|
USB_HUB_EXTENSION* hub = (USB_HUB_EXTENSION*)context;
|
||||||
if (!hub || urb != &hub->ChangeUrb)
|
if (!hub || urb != &hub->ChangeUrb)
|
||||||
@@ -869,7 +844,6 @@ static void UsbHubExternalChangeComplete(USB_URB* urb, void* context) {
|
|||||||
IoReleaseRemoveLock(&hub->RemoveLock, (IRP*)0);
|
IoReleaseRemoveLock(&hub->RemoveLock, (IRP*)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Arm External Interrupt operation.
|
|
||||||
static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub) {
|
static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub) {
|
||||||
if (!hub || !hub->InterruptPipe || !hub->ChangeBitmap || hub->ChangeUrbPending)
|
if (!hub || !hub->InterruptPipe || !hub->ChangeBitmap || hub->ChangeUrbPending)
|
||||||
return;
|
return;
|
||||||
@@ -902,7 +876,6 @@ static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Start Root Device operation.
|
|
||||||
static KSTATUS UsbHubStartRootDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) {
|
static KSTATUS UsbHubStartRootDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) {
|
||||||
hub->PortCount = hub->Hcd ? hub->Hcd->MaxRootPorts : 0;
|
hub->PortCount = hub->Hcd ? hub->Hcd->MaxRootPorts : 0;
|
||||||
if (hub->PortCount > USB_ROOT_HUB_MAX_PORTS)
|
if (hub->PortCount > USB_ROOT_HUB_MAX_PORTS)
|
||||||
@@ -939,7 +912,6 @@ static KSTATUS UsbHubStartRootDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* h
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Start External Device operation.
|
|
||||||
static KSTATUS UsbHubStartExternalDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) {
|
static KSTATUS UsbHubStartExternalDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) {
|
||||||
if (!hub || !hub->Device)
|
if (!hub || !hub->Device)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -1019,7 +991,6 @@ static KSTATUS UsbHubStartExternalDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSIO
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Start Device operation.
|
|
||||||
static KSTATUS UsbHubStartDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) {
|
static KSTATUS UsbHubStartDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) {
|
||||||
if (!device || !hub || hub->Started)
|
if (!device || !hub || hub->Started)
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
@@ -1029,7 +1000,6 @@ static KSTATUS UsbHubStartDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub)
|
|||||||
return UsbHubStartExternalDevice(device, hub);
|
return UsbHubStartExternalDevice(device, hub);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Dispatch Pnp operation.
|
|
||||||
KSTATUS UsbHubDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
KSTATUS UsbHubDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
||||||
if (!device || !irp)
|
if (!device || !irp)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -1154,7 +1124,6 @@ KSTATUS UsbHubDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hub Add Device operation.
|
|
||||||
KSTATUS UsbHubAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
KSTATUS UsbHubAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
||||||
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ static const IO_DRIVER_ID_TABLE gUsbStorageIdTable = {
|
|||||||
sizeof(gUsbStorageIds) / sizeof(gUsbStorageIds[0]),
|
sizeof(gUsbStorageIds) / sizeof(gUsbStorageIds[0]),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements the storage From Disk Device operation.
|
|
||||||
static USB_STORAGE_EXTENSION* UsbStorageFromDiskDevice(DEVICE_OBJECT* device) {
|
static USB_STORAGE_EXTENSION* UsbStorageFromDiskDevice(DEVICE_OBJECT* device) {
|
||||||
if (!device || !device->DeviceExtension)
|
if (!device || !device->DeviceExtension)
|
||||||
return (USB_STORAGE_EXTENSION*)0;
|
return (USB_STORAGE_EXTENSION*)0;
|
||||||
@@ -32,7 +31,6 @@ static USB_STORAGE_EXTENSION* UsbStorageFromDiskDevice(DEVICE_OBJECT* device) {
|
|||||||
return diskExt->Storage;
|
return diskExt->Storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the storage From Interface Device operation.
|
|
||||||
static USB_STORAGE_EXTENSION* UsbStorageFromInterfaceDevice(DEVICE_OBJECT* device) {
|
static USB_STORAGE_EXTENSION* UsbStorageFromInterfaceDevice(DEVICE_OBJECT* device) {
|
||||||
if (!device || !device->DeviceExtension)
|
if (!device || !device->DeviceExtension)
|
||||||
return (USB_STORAGE_EXTENSION*)0;
|
return (USB_STORAGE_EXTENSION*)0;
|
||||||
@@ -43,7 +41,6 @@ static USB_STORAGE_EXTENSION* UsbStorageFromInterfaceDevice(DEVICE_OBJECT* devic
|
|||||||
return ext;
|
return ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the storage Find Bulk Endpoint operation.
|
|
||||||
static const USB_ENDPOINT_DESCRIPTOR* UsbStorageFindBulkEndpoint(const USB_PDO_EXTENSION* pdoExt, bool wantIn) {
|
static const USB_ENDPOINT_DESCRIPTOR* UsbStorageFindBulkEndpoint(const USB_PDO_EXTENSION* pdoExt, bool wantIn) {
|
||||||
if (!pdoExt) return (const USB_ENDPOINT_DESCRIPTOR*)0;
|
if (!pdoExt) return (const USB_ENDPOINT_DESCRIPTOR*)0;
|
||||||
|
|
||||||
@@ -290,7 +287,6 @@ KSTATUS UsbStorageBotCommand(USB_STORAGE_EXTENSION* storage,
|
|||||||
(USB_STORAGE_SENSE_DATA*)0);
|
(USB_STORAGE_SENSE_DATA*)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the be32 operation.
|
|
||||||
uint32_t UsbBe32(const uint8_t* p) {
|
uint32_t UsbBe32(const uint8_t* p) {
|
||||||
return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) |
|
return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) |
|
||||||
((uint32_t)p[2] << 8) | (uint32_t)p[3];
|
((uint32_t)p[2] << 8) | (uint32_t)p[3];
|
||||||
@@ -310,7 +306,6 @@ void UsbStoreBe16(uint8_t* p, uint16_t v) {
|
|||||||
p[1] = (uint8_t)v;
|
p[1] = (uint8_t)v;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the storage Inquiry operation.
|
|
||||||
KSTATUS UsbStorageInquiry(USB_STORAGE_EXTENSION* storage) {
|
KSTATUS UsbStorageInquiry(USB_STORAGE_EXTENSION* storage) {
|
||||||
if (!storage || !storage->XhciDevice)
|
if (!storage || !storage->XhciDevice)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -332,7 +327,6 @@ KSTATUS UsbStorageInquiry(USB_STORAGE_EXTENSION* storage) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the storage Test Unit Ready operation.
|
|
||||||
KSTATUS UsbStorageTestUnitReady(USB_STORAGE_EXTENSION* storage) {
|
KSTATUS UsbStorageTestUnitReady(USB_STORAGE_EXTENSION* storage) {
|
||||||
if (!storage || !storage->XhciDevice)
|
if (!storage || !storage->XhciDevice)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -353,7 +347,6 @@ KSTATUS UsbStorageTestUnitReady(USB_STORAGE_EXTENSION* storage) {
|
|||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the storage Read Capacity operation.
|
|
||||||
KSTATUS UsbStorageReadCapacity(USB_STORAGE_EXTENSION* storage) {
|
KSTATUS UsbStorageReadCapacity(USB_STORAGE_EXTENSION* storage) {
|
||||||
if (!storage || !storage->XhciDevice)
|
if (!storage || !storage->XhciDevice)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -463,7 +456,6 @@ static KSTATUS UsbStorageSynchronizeCache(USB_STORAGE_EXTENSION* storage) {
|
|||||||
return NTLSTATUS_DEVICE_ERROR;
|
return NTLSTATUS_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the storage Acquire Io operation.
|
|
||||||
void UsbStorageAcquireIo(USB_STORAGE_EXTENSION* storage) {
|
void UsbStorageAcquireIo(USB_STORAGE_EXTENSION* storage) {
|
||||||
if (!storage) return;
|
if (!storage) return;
|
||||||
XHCI_CONTROLLER* xhci = storage->Device ? (XHCI_CONTROLLER*)storage->Device->Hcd->ControllerContext : (XHCI_CONTROLLER*)0;
|
XHCI_CONTROLLER* xhci = storage->Device ? (XHCI_CONTROLLER*)storage->Device->Hcd->ControllerContext : (XHCI_CONTROLLER*)0;
|
||||||
@@ -472,12 +464,10 @@ void UsbStorageAcquireIo(USB_STORAGE_EXTENSION* storage) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the storage Release Io operation.
|
|
||||||
void UsbStorageReleaseIo(USB_STORAGE_EXTENSION* storage) {
|
void UsbStorageReleaseIo(USB_STORAGE_EXTENSION* storage) {
|
||||||
if (storage) NtlAtomicExchange32(&storage->IoBusy, 0);
|
if (storage) NtlAtomicExchange32(&storage->IoBusy, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the storage Dispatch Read Write operation.
|
|
||||||
KSTATUS UsbStorageDispatchReadWrite(DEVICE_OBJECT* device, IRP* irp) {
|
KSTATUS UsbStorageDispatchReadWrite(DEVICE_OBJECT* device, IRP* irp) {
|
||||||
if (!device || !irp)
|
if (!device || !irp)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -608,7 +598,6 @@ KSTATUS XhciAllocateMassStorageMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the configure Mass Storage Endpoints operation.
|
|
||||||
KSTATUS XhciConfigureMassStorageEndpoints(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
KSTATUS XhciConfigureMassStorageEndpoints(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
||||||
if (!dev->MassCandidate)
|
if (!dev->MassCandidate)
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
@@ -687,7 +676,6 @@ uint8_t UsbFindFreeDiskIndex(void) {
|
|||||||
return 0xFFu;
|
return 0xFFu;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the storage Register Disk operation.
|
|
||||||
KSTATUS UsbStorageRegisterDisk(USB_STORAGE_EXTENSION* storage) {
|
KSTATUS UsbStorageRegisterDisk(USB_STORAGE_EXTENSION* storage) {
|
||||||
if (!storage || storage->BlockSize != USB_STORAGE_SECTOR_SIZE || storage->BlockCount == 0)
|
if (!storage || storage->BlockSize != USB_STORAGE_SECTOR_SIZE || storage->BlockCount == 0)
|
||||||
return NTLSTATUS_NOT_SUPPORTED;
|
return NTLSTATUS_NOT_SUPPORTED;
|
||||||
@@ -731,7 +719,6 @@ KSTATUS UsbStorageRegisterDisk(USB_STORAGE_EXTENSION* storage) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the storage Start Device operation.
|
|
||||||
static KSTATUS UsbStorageStartDevice(DEVICE_OBJECT* device, USB_STORAGE_EXTENSION* storage) {
|
static KSTATUS UsbStorageStartDevice(DEVICE_OBJECT* device, USB_STORAGE_EXTENSION* storage) {
|
||||||
if (!device || !storage || !storage->InterfacePdo || !storage->Device)
|
if (!device || !storage || !storage->InterfacePdo || !storage->Device)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -849,7 +836,6 @@ fail:
|
|||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the storage Disk Pnp operation.
|
|
||||||
static KSTATUS UsbStorageDiskPnp(DEVICE_OBJECT* device, IRP* irp, USB_STORAGE_EXTENSION* storage, IO_PNP_MINOR_FUNCTION minor) {
|
static KSTATUS UsbStorageDiskPnp(DEVICE_OBJECT* device, IRP* irp, USB_STORAGE_EXTENSION* storage, IO_PNP_MINOR_FUNCTION minor) {
|
||||||
if (!device || !irp || !storage)
|
if (!device || !irp || !storage)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -900,7 +886,6 @@ static KSTATUS UsbStorageDiskPnp(DEVICE_OBJECT* device, IRP* irp, USB_STORAGE_EX
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the storage Interface Pnp operation.
|
|
||||||
static KSTATUS UsbStorageInterfacePnp(DEVICE_OBJECT* device, IRP* irp, USB_STORAGE_EXTENSION* storage, IO_PNP_MINOR_FUNCTION minor) {
|
static KSTATUS UsbStorageInterfacePnp(DEVICE_OBJECT* device, IRP* irp, USB_STORAGE_EXTENSION* storage, IO_PNP_MINOR_FUNCTION minor) {
|
||||||
if (!device || !irp || !storage)
|
if (!device || !irp || !storage)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -978,7 +963,6 @@ static KSTATUS UsbStorageInterfacePnp(DEVICE_OBJECT* device, IRP* irp, USB_STORA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the storage Dispatch Pnp operation.
|
|
||||||
KSTATUS UsbStorageDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
KSTATUS UsbStorageDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
||||||
if (!device || !irp)
|
if (!device || !irp)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -998,7 +982,6 @@ KSTATUS UsbStorageDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
|||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the storage Add Device operation.
|
|
||||||
KSTATUS UsbStorageAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
KSTATUS UsbStorageAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
||||||
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
|
|||||||
+33
-136
@@ -2,52 +2,43 @@
|
|||||||
|
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
// Implements the align Up32 operation.
|
|
||||||
uint32_t UsbAlignUp32(uint32_t value, uint32_t align) {
|
uint32_t UsbAlignUp32(uint32_t value, uint32_t align) {
|
||||||
return (value + align - 1u) & ~(align - 1u);
|
return (value + align - 1u) & ~(align - 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the barrier operation.
|
|
||||||
void XhciBarrier(void) {
|
void XhciBarrier(void) {
|
||||||
_ReadWriteBarrier();
|
_ReadWriteBarrier();
|
||||||
_mm_mfence();
|
_mm_mfence();
|
||||||
_ReadWriteBarrier();
|
_ReadWriteBarrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the read8 operation.
|
|
||||||
uint8_t XhciRead8(volatile uint8_t* base, uint32_t reg) {
|
uint8_t XhciRead8(volatile uint8_t* base, uint32_t reg) {
|
||||||
return *(volatile uint8_t*)(base + reg);
|
return *(volatile uint8_t*)(base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the read16 operation.
|
|
||||||
uint16_t XhciRead16(volatile uint8_t* base, uint32_t reg) {
|
uint16_t XhciRead16(volatile uint8_t* base, uint32_t reg) {
|
||||||
return *(volatile uint16_t*)(base + reg);
|
return *(volatile uint16_t*)(base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the read32 operation.
|
|
||||||
uint32_t XhciRead32(volatile uint8_t* base, uint32_t reg) {
|
uint32_t XhciRead32(volatile uint8_t* base, uint32_t reg) {
|
||||||
return *(volatile uint32_t*)(base + reg);
|
return *(volatile uint32_t*)(base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the write32 operation.
|
|
||||||
void XhciWrite32(volatile uint8_t* base, uint32_t reg, uint32_t value) {
|
void XhciWrite32(volatile uint8_t* base, uint32_t reg, uint32_t value) {
|
||||||
*(volatile uint32_t*)(base + reg) = value;
|
*(volatile uint32_t*)(base + reg) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the read64 operation.
|
|
||||||
uint64_t XhciRead64(volatile uint8_t* base, uint32_t reg) {
|
uint64_t XhciRead64(volatile uint8_t* base, uint32_t reg) {
|
||||||
uint32_t lo = XhciRead32(base, reg);
|
uint32_t lo = XhciRead32(base, reg);
|
||||||
uint32_t hi = XhciRead32(base, reg + 4u);
|
uint32_t hi = XhciRead32(base, reg + 4u);
|
||||||
return ((uint64_t)hi << 32) | lo;
|
return ((uint64_t)hi << 32) | lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the write64 operation.
|
|
||||||
void XhciWrite64(volatile uint8_t* base, uint32_t reg, uint64_t value) {
|
void XhciWrite64(volatile uint8_t* base, uint32_t reg, uint64_t value) {
|
||||||
XhciWrite32(base, reg, (uint32_t)value);
|
XhciWrite32(base, reg, (uint32_t)value);
|
||||||
XhciWrite32(base, reg + 4u, (uint32_t)(value >> 32));
|
XhciWrite32(base, reg + 4u, (uint32_t)(value >> 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the delay Us operation.
|
|
||||||
void UsbDelayUs(uint32_t us) {
|
void UsbDelayUs(uint32_t us) {
|
||||||
KeStallExecution(us);
|
KeStallExecution(us);
|
||||||
}
|
}
|
||||||
@@ -169,43 +160,35 @@ static void XhciReleaseControllerDma(XHCI_CONTROLLER* xhci) {
|
|||||||
xhci->DmaAdapter = (IO_DMA_ADAPTER*)0;
|
xhci->DmaAdapter = (IO_DMA_ADAPTER*)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the scratchpad Count operation.
|
|
||||||
uint16_t XhciScratchpadCount(uint32_t hcs2) {
|
uint16_t XhciScratchpadCount(uint32_t hcs2) {
|
||||||
return (uint16_t)((((hcs2 >> 16) & 0x3E0u) | ((hcs2 >> 27) & 0x1Fu)) & 0x3FFu);
|
return (uint16_t)((((hcs2 >> 16) & 0x3E0u) | ((hcs2 >> 27) & 0x1Fu)) & 0x3FFu);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the trb Type operation.
|
|
||||||
uint32_t XhciTrbType(const XHCI_TRB* trb) {
|
uint32_t XhciTrbType(const XHCI_TRB* trb) {
|
||||||
return (trb->Control >> XHCI_TRB_TYPE_SHIFT) & XHCI_TRB_TYPE_MASK;
|
return (trb->Control >> XHCI_TRB_TYPE_SHIFT) & XHCI_TRB_TYPE_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the completion Code operation.
|
|
||||||
uint32_t XhciCompletionCode(const XHCI_TRB* trb) {
|
uint32_t XhciCompletionCode(const XHCI_TRB* trb) {
|
||||||
return (trb->Status >> 24) & 0xFFu;
|
return (trb->Status >> 24) & 0xFFu;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the event Slot Id operation.
|
|
||||||
uint8_t XhciEventSlotId(const XHCI_TRB* trb) {
|
uint8_t XhciEventSlotId(const XHCI_TRB* trb) {
|
||||||
return (uint8_t)(trb->Control >> 24);
|
return (uint8_t)(trb->Control >> 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the event Endpoint Id operation.
|
|
||||||
uint8_t XhciEventEndpointId(const XHCI_TRB* trb) {
|
uint8_t XhciEventEndpointId(const XHCI_TRB* trb) {
|
||||||
return (uint8_t)((trb->Control >> 16) & 0x1Fu);
|
return (uint8_t)((trb->Control >> 16) & 0x1Fu);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the transfer Residue operation.
|
|
||||||
uint32_t XhciTransferResidue(const XHCI_TRB* trb) {
|
uint32_t XhciTransferResidue(const XHCI_TRB* trb) {
|
||||||
return trb->Status & 0xFFFFFFu;
|
return trb->Status & 0xFFFFFFu;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the input Control Context operation.
|
|
||||||
uint32_t* XhciInputControlContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
uint32_t* XhciInputControlContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
||||||
(void)xhci;
|
(void)xhci;
|
||||||
return (uint32_t*)dev->InputContext;
|
return (uint32_t*)dev->InputContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the input Slot Context operation.
|
|
||||||
uint32_t* XhciInputSlotContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
uint32_t* XhciInputSlotContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
||||||
return (uint32_t*)(dev->InputContext + xhci->ContextBytes);
|
return (uint32_t*)(dev->InputContext + xhci->ContextBytes);
|
||||||
}
|
}
|
||||||
@@ -285,7 +268,6 @@ KSTATUS XhciConfigureHubContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev,
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ep Max Packet operation.
|
|
||||||
uint32_t XhciEpMaxPacket(uint8_t speed) {
|
uint32_t XhciEpMaxPacket(uint8_t speed) {
|
||||||
switch (speed) {
|
switch (speed) {
|
||||||
case 2: return 8; // low-speed
|
case 2: return 8; // low-speed
|
||||||
@@ -297,7 +279,6 @@ uint32_t XhciEpMaxPacket(uint8_t speed) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the setup Packet To U64 operation.
|
|
||||||
uint64_t UsbSetupPacketToU64(const USB_SETUP_PACKET* setup) {
|
uint64_t UsbSetupPacketToU64(const USB_SETUP_PACKET* setup) {
|
||||||
uint64_t v = 0;
|
uint64_t v = 0;
|
||||||
v |= (uint64_t)setup->bmRequestType;
|
v |= (uint64_t)setup->bmRequestType;
|
||||||
@@ -385,7 +366,6 @@ void XhciParseSupportedProtocols(XHCI_CONTROLLER* xhci) {
|
|||||||
(uint32_t)xhci->MaxPorts - usb2Ports - usb3Ports);
|
(uint32_t)xhci->MaxPorts - usb2Ports - usb3Ports);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the port Protocol Major operation.
|
|
||||||
uint8_t XhciPortProtocolMajor(XHCI_CONTROLLER* xhci, uint8_t port, uint32_t portsc) {
|
uint8_t XhciPortProtocolMajor(XHCI_CONTROLLER* xhci, uint8_t port, uint32_t portsc) {
|
||||||
if (port <= XHCI_MAX_ROOT_PORTS && xhci->PortProtocolMajor[port])
|
if (port <= XHCI_MAX_ROOT_PORTS && xhci->PortProtocolMajor[port])
|
||||||
return xhci->PortProtocolMajor[port];
|
return xhci->PortProtocolMajor[port];
|
||||||
@@ -426,7 +406,6 @@ const char* UsbInterfaceClassName(uint8_t klass, uint8_t subclass, uint8_t proto
|
|||||||
return "class";
|
return "class";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the log Port Status operation.
|
|
||||||
void XhciLogPortStatus(XHCI_CONTROLLER* xhci) {
|
void XhciLogPortStatus(XHCI_CONTROLLER* xhci) {
|
||||||
for (uint8_t port = 1; port <= xhci->MaxPorts; port++) {
|
for (uint8_t port = 1; port <= xhci->MaxPorts; port++) {
|
||||||
uint32_t off = XHCI_OP_PORT_BASE + ((uint32_t)port - 1u) * XHCI_OP_PORT_STRIDE;
|
uint32_t off = XHCI_OP_PORT_BASE + ((uint32_t)port - 1u) * XHCI_OP_PORT_STRIDE;
|
||||||
@@ -448,7 +427,6 @@ void XhciLogPortStatus(XHCI_CONTROLLER* xhci) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the power Root Ports operation.
|
|
||||||
void XhciPowerRootPorts(XHCI_CONTROLLER* xhci) {
|
void XhciPowerRootPorts(XHCI_CONTROLLER* xhci) {
|
||||||
if (!xhci || !xhci->Op)
|
if (!xhci || !xhci->Op)
|
||||||
return;
|
return;
|
||||||
@@ -474,7 +452,6 @@ void XhciPowerRootPorts(XHCI_CONTROLLER* xhci) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ack Interrupter0 operation.
|
|
||||||
void XhciAckInterrupter0(XHCI_CONTROLLER* xhci) {
|
void XhciAckInterrupter0(XHCI_CONTROLLER* xhci) {
|
||||||
if (!xhci->Runtime) return;
|
if (!xhci->Runtime) return;
|
||||||
volatile uint8_t* ir0 = xhci->Runtime + 0x20u;
|
volatile uint8_t* ir0 = xhci->Runtime + 0x20u;
|
||||||
@@ -680,7 +657,6 @@ void XhciRegisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target) {
|
|||||||
KeReleaseSpinlock(&xhci->WaitLock, flags);
|
KeReleaseSpinlock(&xhci->WaitLock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the unregister Wait Target operation.
|
|
||||||
void XhciUnregisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target) {
|
void XhciUnregisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target) {
|
||||||
if (!xhci || !target || !target->Registered)
|
if (!xhci || !target || !target->Registered)
|
||||||
return;
|
return;
|
||||||
@@ -761,58 +737,18 @@ void XhciEventDpcRoutine(KDPC* dpc, void* context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define XHCI_CONTROLLER_MAGIC 0x58484349u // XHCI
|
#define XHCI_CONTROLLER_MAGIC 0x58484349u // XHCI
|
||||||
#define XHCI_MAX_CONTROLLERS 8u
|
void XhciIsr(void* context) {
|
||||||
|
XHCI_CONTROLLER* xhci = (XHCI_CONTROLLER*)context;
|
||||||
static XHCI_CONTROLLER* gXhciControllers[XHCI_MAX_CONTROLLERS];
|
if (!xhci || !xhci->Running || !xhci->Op || !xhci->Runtime) return;
|
||||||
static uint32_t gXhciControllerCount;
|
uint32_t status = XhciRead32(xhci->Op, XHCI_OP_USBSTS);
|
||||||
|
if (!(status & (XHCI_USBSTS_EINT | XHCI_USBSTS_PCD | XHCI_USBSTS_HSE | XHCI_USBSTS_HCE)))
|
||||||
// Registers controller.
|
|
||||||
static KSTATUS XhciRegisterController(XHCI_CONTROLLER* xhci) {
|
|
||||||
if (!xhci) return NTLSTATUS_INVALID_PARAMETER;
|
|
||||||
for (uint32_t i = 0; i < gXhciControllerCount; i++) {
|
|
||||||
if (gXhciControllers[i] == xhci)
|
|
||||||
return NTLSTATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
if (gXhciControllerCount >= XHCI_MAX_CONTROLLERS)
|
|
||||||
return NTLSTATUS_NO_MEMORY;
|
|
||||||
gXhciControllers[gXhciControllerCount++] = xhci;
|
|
||||||
return NTLSTATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes a controller from the interrupt-dispatch registry.
|
|
||||||
static void XhciUnregisterController(XHCI_CONTROLLER* xhci) {
|
|
||||||
if (!xhci)
|
|
||||||
return;
|
return;
|
||||||
for (uint32_t i = 0; i < gXhciControllerCount; i++) {
|
xhci->InterruptCount++;
|
||||||
if (gXhciControllers[i] != xhci)
|
XhciWrite32(xhci->Op, XHCI_OP_USBSTS, status & XHCI_USBSTS_CLEAR_MASK);
|
||||||
continue;
|
XhciAckInterrupter0(xhci);
|
||||||
for (uint32_t next = i + 1; next < gXhciControllerCount; next++)
|
KeInsertQueueDpc(&xhci->EventDpc, (void*)0, (void*)0);
|
||||||
gXhciControllers[next - 1] = gXhciControllers[next];
|
|
||||||
gXhciControllerCount--;
|
|
||||||
gXhciControllers[gXhciControllerCount] = (XHCI_CONTROLLER*)0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the isr operation.
|
|
||||||
void XhciIsr(void) {
|
|
||||||
for (uint32_t i = 0; i < gXhciControllerCount; i++) {
|
|
||||||
XHCI_CONTROLLER* xhci = gXhciControllers[i];
|
|
||||||
if (!xhci || !xhci->Running || !xhci->Op || !xhci->Runtime)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uint32_t status = XhciRead32(xhci->Op, XHCI_OP_USBSTS);
|
|
||||||
if (!(status & (XHCI_USBSTS_EINT | XHCI_USBSTS_PCD | XHCI_USBSTS_HSE | XHCI_USBSTS_HCE)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
xhci->InterruptCount++;
|
|
||||||
XhciWrite32(xhci->Op, XHCI_OP_USBSTS, status & XHCI_USBSTS_CLEAR_MASK);
|
|
||||||
XhciAckInterrupter0(xhci);
|
|
||||||
KeInsertQueueDpc(&xhci->EventDpc, (void*)0, (void*)0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements the bios Handoff operation.
|
|
||||||
KSTATUS XhciBiosHandoff(XHCI_CONTROLLER* xhci) {
|
KSTATUS XhciBiosHandoff(XHCI_CONTROLLER* xhci) {
|
||||||
uint32_t xecp = (xhci->Hcc1 >> 16) & 0xFFFFu;
|
uint32_t xecp = (xhci->Hcc1 >> 16) & 0xFFFFu;
|
||||||
if (!xecp) return NTLSTATUS_SUCCESS;
|
if (!xecp) return NTLSTATUS_SUCCESS;
|
||||||
@@ -856,7 +792,6 @@ KSTATUS XhciBiosHandoff(XHCI_CONTROLLER* xhci) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the stop And Reset operation.
|
|
||||||
KSTATUS XhciStopAndReset(XHCI_CONTROLLER* xhci) {
|
KSTATUS XhciStopAndReset(XHCI_CONTROLLER* xhci) {
|
||||||
uint32_t cmd = XhciRead32(xhci->Op, XHCI_OP_USBCMD);
|
uint32_t cmd = XhciRead32(xhci->Op, XHCI_OP_USBCMD);
|
||||||
if (cmd & XHCI_USBCMD_RS) {
|
if (cmd & XHCI_USBCMD_RS) {
|
||||||
@@ -991,7 +926,6 @@ KSTATUS XhciAllocateRuntimeMemory(XHCI_CONTROLLER* xhci) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the program Runtime operation.
|
|
||||||
KSTATUS XhciProgramRuntime(XHCI_CONTROLLER* xhci) {
|
KSTATUS XhciProgramRuntime(XHCI_CONTROLLER* xhci) {
|
||||||
uint8_t slots = xhci->MaxSlots;
|
uint8_t slots = xhci->MaxSlots;
|
||||||
if (slots == 0) return NTLSTATUS_DEVICE_ERROR;
|
if (slots == 0) return NTLSTATUS_DEVICE_ERROR;
|
||||||
@@ -1159,7 +1093,6 @@ KSTATUS XhciDisableSlot(XHCI_CONTROLLER* xhci, uint8_t slotId) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the address Device operation.
|
|
||||||
KSTATUS XhciAddressDevice(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
KSTATUS XhciAddressDevice(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
||||||
XHCI_COMMAND_RESULT result;
|
XHCI_COMMAND_RESULT result;
|
||||||
memset(&result, 0, sizeof(result));
|
memset(&result, 0, sizeof(result));
|
||||||
@@ -1206,7 +1139,6 @@ void XhciEnableInterrupts(XHCI_CONTROLLER* xhci) {
|
|||||||
XhciWrite32(xhci->Op, XHCI_OP_USBCMD, cmd | XHCI_USBCMD_INTE | XHCI_USBCMD_HSEE);
|
XhciWrite32(xhci->Op, XHCI_OP_USBCMD, cmd | XHCI_USBCMD_INTE | XHCI_USBCMD_HSEE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the port Reg operation.
|
|
||||||
uint32_t XhciPortReg(uint8_t port) {
|
uint32_t XhciPortReg(uint8_t port) {
|
||||||
return XHCI_OP_PORT_BASE + ((uint32_t)port - 1u) * XHCI_OP_PORT_STRIDE;
|
return XHCI_OP_PORT_BASE + ((uint32_t)port - 1u) * XHCI_OP_PORT_STRIDE;
|
||||||
}
|
}
|
||||||
@@ -1227,7 +1159,6 @@ void XhciClearPortChanges(XHCI_CONTROLLER* xhci, uint8_t port) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the reset Port operation.
|
|
||||||
KSTATUS XhciResetPort(XHCI_CONTROLLER* xhci, uint8_t port, uint8_t* outSpeed) {
|
KSTATUS XhciResetPort(XHCI_CONTROLLER* xhci, uint8_t port, uint8_t* outSpeed) {
|
||||||
uint32_t off = XhciPortReg(port);
|
uint32_t off = XhciPortReg(port);
|
||||||
uint32_t portsc = XhciRead32(xhci->Op, off);
|
uint32_t portsc = XhciRead32(xhci->Op, off);
|
||||||
@@ -1647,14 +1578,12 @@ KSTATUS XhciGetConfigurationDescriptor(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev,
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the endpoint Id From Address operation.
|
|
||||||
uint8_t XhciEndpointIdFromAddress(uint8_t endpointAddress) {
|
uint8_t XhciEndpointIdFromAddress(uint8_t endpointAddress) {
|
||||||
uint8_t number = endpointAddress & USB_ENDPOINT_NUMBER_MASK;
|
uint8_t number = endpointAddress & USB_ENDPOINT_NUMBER_MASK;
|
||||||
if (number == 0) return 1;
|
if (number == 0) return 1;
|
||||||
return (uint8_t)(number * 2u + ((endpointAddress & USB_ENDPOINT_DIR_IN) ? 1u : 0u));
|
return (uint8_t)(number * 2u + ((endpointAddress & USB_ENDPOINT_DIR_IN) ? 1u : 0u));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the interrupt Interval operation.
|
|
||||||
uint8_t XhciInterruptInterval(uint8_t speed, uint8_t usbInterval) {
|
uint8_t XhciInterruptInterval(uint8_t speed, uint8_t usbInterval) {
|
||||||
if (usbInterval == 0) usbInterval = 1;
|
if (usbInterval == 0) usbInterval = 1;
|
||||||
|
|
||||||
@@ -1781,7 +1710,6 @@ KSTATUS XhciBulkTransfer(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev,
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the configure Pipe Endpoint operation.
|
|
||||||
KSTATUS XhciConfigurePipeEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_PIPE* pipe) {
|
KSTATUS XhciConfigurePipeEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_PIPE* pipe) {
|
||||||
if (!xhci || !dev || !pipe || !pipe->Open)
|
if (!xhci || !dev || !pipe || !pipe->Open)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -1868,7 +1796,6 @@ KSTATUS XhciConfigurePipeEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_P
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hcd Submit Interrupt Urb operation.
|
|
||||||
static KSTATUS XhciHcdSubmitInterruptUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_URB* urb) {
|
static KSTATUS XhciHcdSubmitInterruptUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_URB* urb) {
|
||||||
if (!xhci || !dev || !urb || !urb->Pipe || !urb->BufferDeviceAddress || urb->Length == 0)
|
if (!xhci || !dev || !urb || !urb->Pipe || !urb->BufferDeviceAddress || urb->Length == 0)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -1966,7 +1893,6 @@ static bool XhciClaimAsyncCompletion(XHCI_CONTROLLER* xhci, uint64_t trbDeviceAd
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hcd Submit Bulk Urb operation.
|
|
||||||
static KSTATUS XhciHcdSubmitBulkUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_URB* urb) {
|
static KSTATUS XhciHcdSubmitBulkUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_URB* urb) {
|
||||||
if (!xhci || !dev || !urb || !urb->Pipe || !urb->BufferDeviceAddress || urb->Length == 0)
|
if (!xhci || !dev || !urb || !urb->Pipe || !urb->BufferDeviceAddress || urb->Length == 0)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -2006,7 +1932,6 @@ static KSTATUS XhciHcdSubmitBulkUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB
|
|||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hcd Submit Urb operation.
|
|
||||||
static KSTATUS XhciHcdSubmitUrb(USB_HCD* hcd, USB_URB* urb) {
|
static KSTATUS XhciHcdSubmitUrb(USB_HCD* hcd, USB_URB* urb) {
|
||||||
if (!hcd || !urb || !urb->Device)
|
if (!hcd || !urb || !urb->Device)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -2105,7 +2030,6 @@ static KSTATUS XhciHcdCancelUrb(USB_HCD* hcd, USB_URB* urb) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hcd Allocate Dma operation.
|
|
||||||
static void* XhciHcdAllocateDma(USB_HCD* hcd,
|
static void* XhciHcdAllocateDma(USB_HCD* hcd,
|
||||||
size_t pages,
|
size_t pages,
|
||||||
uint64_t* outDeviceAddress,
|
uint64_t* outDeviceAddress,
|
||||||
@@ -2130,13 +2054,11 @@ static void XhciHcdDestroyPipe(USB_HCD* hcd, USB_PIPE* pipe) {
|
|||||||
MmFreePool(ctx);
|
MmFreePool(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hcd Reset Root Port operation.
|
|
||||||
static KSTATUS XhciHcdResetRootPort(USB_HCD* hcd, uint8_t port, uint8_t* outSpeed) {
|
static KSTATUS XhciHcdResetRootPort(USB_HCD* hcd, uint8_t port, uint8_t* outSpeed) {
|
||||||
if (!hcd) return NTLSTATUS_INVALID_PARAMETER;
|
if (!hcd) return NTLSTATUS_INVALID_PARAMETER;
|
||||||
return XhciResetPort((XHCI_CONTROLLER*)hcd->ControllerContext, port, outSpeed);
|
return XhciResetPort((XHCI_CONTROLLER*)hcd->ControllerContext, port, outSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the hcd Clear Root Port Changes operation.
|
|
||||||
static KSTATUS XhciHcdClearRootPortChanges(USB_HCD* hcd, uint8_t port) {
|
static KSTATUS XhciHcdClearRootPortChanges(USB_HCD* hcd, uint8_t port) {
|
||||||
if (!hcd) return NTLSTATUS_INVALID_PARAMETER;
|
if (!hcd) return NTLSTATUS_INVALID_PARAMETER;
|
||||||
XhciClearPortChanges((XHCI_CONTROLLER*)hcd->ControllerContext, port);
|
XhciClearPortChanges((XHCI_CONTROLLER*)hcd->ControllerContext, port);
|
||||||
@@ -2181,35 +2103,13 @@ KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) {
|
|||||||
return NTLSTATUS_DEVICE_ERROR;
|
return NTLSTATUS_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
xhci->Irq = 0xFFu;
|
xhci->InterruptRequest.Routine = XhciIsr;
|
||||||
|
xhci->InterruptRequest.Context = xhci;
|
||||||
|
xhci->InterruptRequest.Affinity = 0;
|
||||||
|
xhci->InterruptRequest.Interrupt = (KE_INTERRUPT*)0;
|
||||||
xhci->UsingMsi = false;
|
xhci->UsingMsi = false;
|
||||||
|
st = PciEnableDevice(xhci->Pdo, PCI_ENABLE_MEMORY | PCI_ENABLE_BUSMASTER | PCI_DISABLE_INTX);
|
||||||
st = PciEnableMsiAuto(xhci->Pdo, &xhci->Irq);
|
if (!KSUCCESS(st)) return st;
|
||||||
if (KSUCCESS(st)) {
|
|
||||||
xhci->UsingMsi = true;
|
|
||||||
DbgPrint("usb: xHCI using MSI IRQ slot %u\n", xhci->Irq);
|
|
||||||
} else {
|
|
||||||
KSTATUS intxStatus = PciGetInterrupt(xhci->Pdo, &xhci->Irq);
|
|
||||||
if (KSUCCESS(intxStatus) && xhci->Irq != 0xFFu) {
|
|
||||||
DbgPrint("usb: xHCI using legacy INTx IRQ %u\n", xhci->Irq);
|
|
||||||
} else {
|
|
||||||
xhci->Irq = 0xFFu;
|
|
||||||
DbgPrint("usb: xHCI no MSI/INTx interrupt available; using polled event-ring mode (msi=0x%x intx=0x%x)\n",
|
|
||||||
st, intxStatus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t enableFlags = PCI_ENABLE_MEMORY | PCI_ENABLE_BUSMASTER;
|
|
||||||
if (xhci->UsingMsi || xhci->Irq == 0xFFu)
|
|
||||||
enableFlags |= PCI_DISABLE_INTX;
|
|
||||||
else
|
|
||||||
enableFlags |= PCI_ENABLE_INTX;
|
|
||||||
|
|
||||||
st = PciEnableDevice(xhci->Pdo, enableFlags);
|
|
||||||
if (!KSUCCESS(st)) {
|
|
||||||
DbgPrint("usb: xHCI PciEnableDevice failed st=0x%x\n", st);
|
|
||||||
return st;
|
|
||||||
}
|
|
||||||
|
|
||||||
xhci->MmioPhys = xhci->MmioBar.Base;
|
xhci->MmioPhys = xhci->MmioBar.Base;
|
||||||
|
|
||||||
@@ -2266,12 +2166,11 @@ KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) {
|
|||||||
UsbInitializeHcd(&xhci->Hcd, &gXhciHcdOperations, xhci, 0, xhci->MaxPorts);
|
UsbInitializeHcd(&xhci->Hcd, &gXhciHcdOperations, xhci, 0, xhci->MaxPorts);
|
||||||
xhci->Hcd.ControllerDevice = xhci->Fdo;
|
xhci->Hcd.ControllerDevice = xhci->Fdo;
|
||||||
|
|
||||||
DbgPrint("usb: xHCI init %02x:%02x.%x vendor=%04x device=%04x irq=%u mmio=0x%016llX caplen=%u version=%04x\n",
|
UsbTrace("usb: xHCI init %02x:%02x.%x vendor=%04x device=%04x mmio=0x%016llX caplen=%u version=%04x\n",
|
||||||
xhci->Bus, xhci->Dev, xhci->Fn,
|
xhci->Bus, xhci->Dev, xhci->Fn,
|
||||||
xhci->PciInfo.VendorId, xhci->PciInfo.DeviceId,
|
xhci->PciInfo.VendorId, xhci->PciInfo.DeviceId,
|
||||||
xhci->Irq,
|
|
||||||
(unsigned long long)xhci->MmioPhys, xhci->CapLength, xhci->Version);
|
(unsigned long long)xhci->MmioPhys, xhci->CapLength, xhci->Version);
|
||||||
DbgPrint("usb: xHCI caps slots=%u intrs=%u ports=%u ctx=%u scratchpads=%u hcs2=%08x hcc1=%08x dboff=0x%x rtsoff=0x%x pagesize=%08x\n",
|
UsbTrace("usb: xHCI caps slots=%u intrs=%u ports=%u ctx=%u scratchpads=%u hcs2=%08x hcc1=%08x dboff=0x%x rtsoff=0x%x pagesize=%08x\n",
|
||||||
xhci->MaxSlots, xhci->MaxIntrs, xhci->MaxPorts, xhci->ContextBytes,
|
xhci->MaxSlots, xhci->MaxIntrs, xhci->MaxPorts, xhci->ContextBytes,
|
||||||
xhci->ScratchpadCount, xhci->Hcs2, xhci->Hcc1, xhci->DbOff,
|
xhci->ScratchpadCount, xhci->Hcs2, xhci->Hcc1, xhci->DbOff,
|
||||||
xhci->RtsOff, XhciRead32(xhci->Op, XHCI_OP_PAGESIZE));
|
xhci->RtsOff, XhciRead32(xhci->Op, XHCI_OP_PAGESIZE));
|
||||||
@@ -2331,22 +2230,18 @@ KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) {
|
|||||||
goto failDma;
|
goto failDma;
|
||||||
}
|
}
|
||||||
|
|
||||||
st = XhciRegisterController(xhci);
|
st = PciConnectInterrupts(xhci->Pdo, &xhci->InterruptRequest, 1u, &xhci->UsingMsi);
|
||||||
if (!KSUCCESS(st)) {
|
if (KSUCCESS(st)) {
|
||||||
DbgPrint("usb: xHCI controller registry full st=0x%x\n", st);
|
|
||||||
goto failDma;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xhci->Irq != 0xFFu) {
|
|
||||||
KeIrqRegister(xhci->Irq, XhciIsr);
|
|
||||||
XhciEnableInterrupts(xhci);
|
XhciEnableInterrupts(xhci);
|
||||||
xhci->InterruptsEnabled = true;
|
xhci->InterruptsEnabled = true;
|
||||||
KeInsertQueueDpc(&xhci->EventDpc, (void*)0, (void*)0);
|
KeInsertQueueDpc(&xhci->EventDpc, (void*)0, (void*)0);
|
||||||
DbgPrint("usb: xHCI ISR registered on IRQ %u (%s); event ring handled by DPC\n",
|
KE_INTERRUPT_INFO info;
|
||||||
xhci->Irq, xhci->UsingMsi ? "MSI" : "INTx");
|
if (KSUCCESS(KeInterruptQuery(xhci->InterruptRequest.Interrupt, &info)))
|
||||||
|
DbgPrint("usb: xHCI interrupt cpu=%u vector=0x%02x mode=%s\n",
|
||||||
|
info.CpuIndex, info.Vector, xhci->UsingMsi ? "MSI/MSI-X" : "INTx");
|
||||||
} else {
|
} else {
|
||||||
xhci->InterruptsEnabled = false;
|
xhci->InterruptsEnabled = false;
|
||||||
DbgPrint("usb: xHCI started in polling mode; synchronous waits drain event ring\n");
|
DbgPrint("usb: xHCI polling fallback status=0x%x\n", st);
|
||||||
}
|
}
|
||||||
xhci->Fdo->PnpState = DevicePnpStarted;
|
xhci->Fdo->PnpState = DevicePnpStarted;
|
||||||
|
|
||||||
@@ -2354,15 +2249,16 @@ KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) {
|
|||||||
if (!KSUCCESS(st))
|
if (!KSUCCESS(st))
|
||||||
DbgPrint("usb: root hub async scan scheduling failed st=0x%x\n", st);
|
DbgPrint("usb: root hub async scan scheduling failed st=0x%x\n", st);
|
||||||
else
|
else
|
||||||
DbgPrint("usb: root hub initial scan requested\n");
|
UsbTrace("usb: root hub scan scheduled\n");
|
||||||
|
|
||||||
DbgPrint("usb: xHCI host controller initialised; HID boot input active=%u mass-storage will arrive through hotplug\n",
|
DbgPrint("usb: xHCI ready pci=%02x:%02x.%u ports=%u\n",
|
||||||
xhci->HidDeviceCount);
|
xhci->Bus, xhci->Dev, xhci->Fn, xhci->MaxPorts);
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
|
|
||||||
failDma:
|
failDma:
|
||||||
XhciHaltForDmaRelease(xhci);
|
XhciHaltForDmaRelease(xhci);
|
||||||
XhciUnregisterController(xhci);
|
if (xhci->InterruptRequest.Interrupt)
|
||||||
|
PciDisconnectInterrupts(xhci->Pdo, &xhci->InterruptRequest, 1u);
|
||||||
if (xhci->Hcd.RootHubPdo) {
|
if (xhci->Hcd.RootHubPdo) {
|
||||||
(void)UsbRemovePdoSubtree(xhci->Hcd.RootHubPdo, true);
|
(void)UsbRemovePdoSubtree(xhci->Hcd.RootHubPdo, true);
|
||||||
xhci->Hcd.RootHubPdo = (DEVICE_OBJECT*)0;
|
xhci->Hcd.RootHubPdo = (DEVICE_OBJECT*)0;
|
||||||
@@ -2400,6 +2296,8 @@ KSTATUS XhciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
|||||||
xhci->SurpriseRemoved = true;
|
xhci->SurpriseRemoved = true;
|
||||||
xhci->Running = false;
|
xhci->Running = false;
|
||||||
xhci->InterruptsEnabled = false;
|
xhci->InterruptsEnabled = false;
|
||||||
|
if (xhci->InterruptRequest.Interrupt)
|
||||||
|
PciDisconnectInterrupts(xhci->Pdo, &xhci->InterruptRequest, 1u);
|
||||||
if (xhci->Hcd.RootHubPdo)
|
if (xhci->Hcd.RootHubPdo)
|
||||||
(void)UsbRemovePdoSubtree(xhci->Hcd.RootHubPdo, true);
|
(void)UsbRemovePdoSubtree(xhci->Hcd.RootHubPdo, true);
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
@@ -2407,11 +2305,12 @@ KSTATUS XhciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
|||||||
case IRP_MN_REMOVE_DEVICE:
|
case IRP_MN_REMOVE_DEVICE:
|
||||||
device->PnpState = DevicePnpDeleted;
|
device->PnpState = DevicePnpDeleted;
|
||||||
XhciHaltForDmaRelease(xhci);
|
XhciHaltForDmaRelease(xhci);
|
||||||
|
if (xhci->InterruptRequest.Interrupt)
|
||||||
|
PciDisconnectInterrupts(xhci->Pdo, &xhci->InterruptRequest, 1u);
|
||||||
if (xhci->Hcd.RootHubPdo) {
|
if (xhci->Hcd.RootHubPdo) {
|
||||||
(void)UsbRemovePdoSubtree(xhci->Hcd.RootHubPdo, true);
|
(void)UsbRemovePdoSubtree(xhci->Hcd.RootHubPdo, true);
|
||||||
xhci->Hcd.RootHubPdo = (DEVICE_OBJECT*)0;
|
xhci->Hcd.RootHubPdo = (DEVICE_OBJECT*)0;
|
||||||
}
|
}
|
||||||
XhciUnregisterController(xhci);
|
|
||||||
XhciReleaseControllerDma(xhci);
|
XhciReleaseControllerDma(xhci);
|
||||||
IoDetachDevice(device);
|
IoDetachDevice(device);
|
||||||
IoDeleteDevice(device);
|
IoDeleteDevice(device);
|
||||||
@@ -2422,7 +2321,6 @@ KSTATUS XhciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the add Device operation.
|
|
||||||
KSTATUS XhciAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
KSTATUS XhciAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
||||||
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -2439,7 +2337,6 @@ KSTATUS XhciAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject
|
|||||||
|
|
||||||
xhci->Fdo = fdo;
|
xhci->Fdo = fdo;
|
||||||
xhci->Pdo = physicalDeviceObject;
|
xhci->Pdo = physicalDeviceObject;
|
||||||
xhci->Irq = 0xFFu;
|
|
||||||
KeInitializeDpc(&xhci->EventDpc, XhciEventDpcRoutine, xhci);
|
KeInitializeDpc(&xhci->EventDpc, XhciEventDpcRoutine, xhci);
|
||||||
|
|
||||||
xhci->LowerDevice = IoAttachDeviceToDeviceStack(fdo, physicalDeviceObject);
|
xhci->LowerDevice = IoAttachDeviceToDeviceStack(fdo, physicalDeviceObject);
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
DIRS=bus input storage audio fs display net platform
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DIRS=vmwaresvga
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!include $(BASEDIR)\makefile.def
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
TARGETNAME=vmwaresvga
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=DRIVER
|
||||||
|
FLAVOR=DRIVER
|
||||||
|
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\pci.lib"
|
||||||
|
EXTRA_LFLAGS=/NOENTRY
|
||||||
|
SOURCES=@/code/drivers/display/vmwaresvga/vmwaresvga.c
|
||||||
@@ -213,7 +213,6 @@ static void VmwSvgaWakeFifo(VMWSVGA_DEVICE* v) {
|
|||||||
|
|
||||||
static KSTATUS VmwSvgaUploadCursorImage(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels);
|
static KSTATUS VmwSvgaUploadCursorImage(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels);
|
||||||
|
|
||||||
// Implements the premultiply Argb For Bgra operation.
|
|
||||||
static uint32_t VmwSvgaPremultiplyArgbForBgra(uint32_t argb) {
|
static uint32_t VmwSvgaPremultiplyArgbForBgra(uint32_t argb) {
|
||||||
uint32_t a = argb >> 24;
|
uint32_t a = argb >> 24;
|
||||||
if (a == 0)
|
if (a == 0)
|
||||||
@@ -231,7 +230,6 @@ static uint32_t VmwSvgaPremultiplyArgbForBgra(uint32_t argb) {
|
|||||||
return (a << 24) | (r << 16) | (g << 8) | b;
|
return (a << 24) | (r << 16) | (g << 8) | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the cursor Commit operation.
|
|
||||||
static void VmwSvgaCursorCommit(VMWSVGA_DEVICE* v) {
|
static void VmwSvgaCursorCommit(VMWSVGA_DEVICE* v) {
|
||||||
if (!v || !v->HardwareCursor || !v->CursorImageDefined)
|
if (!v || !v->HardwareCursor || !v->CursorImageDefined)
|
||||||
return;
|
return;
|
||||||
@@ -266,7 +264,6 @@ static void VmwSvgaCursorCommit(VMWSVGA_DEVICE* v) {
|
|||||||
VmwSvgaWriteReg(v, SVGA_REG_CURSOR_ON, v->CursorVisible ? SVGA_CURSOR_ON_SHOW : SVGA_CURSOR_ON_HIDE);
|
VmwSvgaWriteReg(v, SVGA_REG_CURSOR_ON, v->CursorVisible ? SVGA_CURSOR_ON_SHOW : SVGA_CURSOR_ON_HIDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the cursor Set Visible operation.
|
|
||||||
static void VmwSvgaCursorSetVisible(VMWSVGA_DEVICE* v, bool visible) {
|
static void VmwSvgaCursorSetVisible(VMWSVGA_DEVICE* v, bool visible) {
|
||||||
if (!v || !v->HardwareCursor)
|
if (!v || !v->HardwareCursor)
|
||||||
return;
|
return;
|
||||||
@@ -274,7 +271,6 @@ static void VmwSvgaCursorSetVisible(VMWSVGA_DEVICE* v, bool visible) {
|
|||||||
VmwSvgaCursorCommit(v);
|
VmwSvgaCursorCommit(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the cursor Set Position operation.
|
|
||||||
static void VmwSvgaCursorSetPosition(VMWSVGA_DEVICE* v, int32_t x, int32_t y) {
|
static void VmwSvgaCursorSetPosition(VMWSVGA_DEVICE* v, int32_t x, int32_t y) {
|
||||||
if (!v || !v->HardwareCursor)
|
if (!v || !v->HardwareCursor)
|
||||||
return;
|
return;
|
||||||
@@ -283,7 +279,6 @@ static void VmwSvgaCursorSetPosition(VMWSVGA_DEVICE* v, int32_t x, int32_t y) {
|
|||||||
VmwSvgaCursorCommit(v);
|
VmwSvgaCursorCommit(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the define Alpha Cursor operation.
|
|
||||||
static KSTATUS VmwSvgaDefineAlphaCursor(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) {
|
static KSTATUS VmwSvgaDefineAlphaCursor(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) {
|
||||||
KSTATUS st = VmwSvgaFifoWrite(v, SVGA_CMD_DEFINE_ALPHA_CURSOR);
|
KSTATUS st = VmwSvgaFifoWrite(v, SVGA_CMD_DEFINE_ALPHA_CURSOR);
|
||||||
if (!KSUCCESS(st)) return st;
|
if (!KSUCCESS(st)) return st;
|
||||||
@@ -342,7 +337,6 @@ static uint32_t VmwSvgaPackMonoCursorDword(const uint8_t* bits,
|
|||||||
((uint32_t)bytes[3] << 24);
|
((uint32_t)bytes[3] << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the classic Cursor Width operation.
|
|
||||||
static int32_t VmwSvgaClassicCursorWidth(int32_t width) {
|
static int32_t VmwSvgaClassicCursorWidth(int32_t width) {
|
||||||
|
|
||||||
// QEMU's VMware SVGA implementation reads classic cursor masks as
|
// QEMU's VMware SVGA implementation reads classic cursor masks as
|
||||||
@@ -399,7 +393,6 @@ static void VmwSvgaBuildMonoCursorBits(const uint32_t* argbPixels,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the define Classic Cursor operation.
|
|
||||||
static KSTATUS VmwSvgaDefineClassicCursor(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) {
|
static KSTATUS VmwSvgaDefineClassicCursor(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) {
|
||||||
int32_t encodedWidth = VmwSvgaClassicCursorWidth(width);
|
int32_t encodedWidth = VmwSvgaClassicCursorWidth(width);
|
||||||
uint32_t dwordsPerRow = ((uint32_t)encodedWidth + 31u) / 32u;
|
uint32_t dwordsPerRow = ((uint32_t)encodedWidth + 31u) / 32u;
|
||||||
@@ -460,7 +453,6 @@ done:
|
|||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the upload Cursor Image operation.
|
|
||||||
static KSTATUS VmwSvgaUploadCursorImage(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) {
|
static KSTATUS VmwSvgaUploadCursorImage(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) {
|
||||||
if (!v || !v->HardwareCursor || !argbPixels || width <= 0 || height <= 0)
|
if (!v || !v->HardwareCursor || !argbPixels || width <= 0 || height <= 0)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -478,7 +470,6 @@ static KSTATUS VmwSvgaUploadCursorImage(VMWSVGA_DEVICE* v, int32_t width, int32_
|
|||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the define Cursor Image operation.
|
|
||||||
static KSTATUS VmwSvgaDefineCursorImage(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) {
|
static KSTATUS VmwSvgaDefineCursorImage(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) {
|
||||||
if (!v || !v->HardwareCursor || !argbPixels || width <= 0 || height <= 0)
|
if (!v || !v->HardwareCursor || !argbPixels || width <= 0 || height <= 0)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -509,12 +500,10 @@ static KSTATUS VmwSvgaDefineCursorImage(VMWSVGA_DEVICE* v, int32_t width, int32_
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the align Up32 operation.
|
|
||||||
static uint32_t VmwSvgaAlignUp32(uint32_t value, uint32_t alignment) {
|
static uint32_t VmwSvgaAlignUp32(uint32_t value, uint32_t alignment) {
|
||||||
return (value + alignment - 1u) & ~(alignment - 1u);
|
return (value + alignment - 1u) & ~(alignment - 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the define Screen Object operation.
|
|
||||||
static KSTATUS VmwSvgaDefineScreenObject(VMWSVGA_DEVICE* v) {
|
static KSTATUS VmwSvgaDefineScreenObject(VMWSVGA_DEVICE* v) {
|
||||||
if (!v || !v->FifoReady || !v->UseScreenObject)
|
if (!v || !v->FifoReady || !v->UseScreenObject)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -549,7 +538,6 @@ static KSTATUS VmwSvgaDefineScreenObject(VMWSVGA_DEVICE* v) {
|
|||||||
return VmwSvgaSyncDevice(v);
|
return VmwSvgaSyncDevice(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the define Gmrfb operation.
|
|
||||||
static KSTATUS VmwSvgaDefineGmrfb(VMWSVGA_DEVICE* v) {
|
static KSTATUS VmwSvgaDefineGmrfb(VMWSVGA_DEVICE* v) {
|
||||||
if (!v || !v->FifoReady || !v->UseScreenObject)
|
if (!v || !v->FifoReady || !v->UseScreenObject)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -658,7 +646,6 @@ static KSTATUS VmwSvgaInitializeScreenObject(VMWSVGA_DEVICE* v) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the legacy Update operation.
|
|
||||||
static KSTATUS VmwSvgaLegacyUpdate(VMWSVGA_DEVICE* v, int32_t x, int32_t y, int32_t w, int32_t h) {
|
static KSTATUS VmwSvgaLegacyUpdate(VMWSVGA_DEVICE* v, int32_t x, int32_t y, int32_t w, int32_t h) {
|
||||||
DISPLAY_RECT r = { x, y, w, h };
|
DISPLAY_RECT r = { x, y, w, h };
|
||||||
if (!VmwSvgaClipRect(v, &r))
|
if (!VmwSvgaClipRect(v, &r))
|
||||||
@@ -712,7 +699,6 @@ static KSTATUS VmwSvgaSyncDevice(VMWSVGA_DEVICE* v) {
|
|||||||
return NTLSTATUS_TIMEOUT;
|
return NTLSTATUS_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the blend Pixel operation.
|
|
||||||
static uint32_t VmwSvgaBlendPixel(uint32_t dst, uint32_t src) {
|
static uint32_t VmwSvgaBlendPixel(uint32_t dst, uint32_t src) {
|
||||||
uint8_t a = (uint8_t)(src >> 24);
|
uint8_t a = (uint8_t)(src >> 24);
|
||||||
if (a == 0) return dst;
|
if (a == 0) return dst;
|
||||||
@@ -731,12 +717,10 @@ static uint32_t VmwSvgaBlendPixel(uint32_t dst, uint32_t src) {
|
|||||||
return ((uint32_t)rr << 16) | ((uint32_t)gg << 8) | bb;
|
return ((uint32_t)rr << 16) | ((uint32_t)gg << 8) | bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the from Display operation.
|
|
||||||
static VMWSVGA_DEVICE* VmwSvgaFromDisplay(DISPLAY_DEVICE* device) {
|
static VMWSVGA_DEVICE* VmwSvgaFromDisplay(DISPLAY_DEVICE* device) {
|
||||||
return device ? (VMWSVGA_DEVICE*)device->DriverContext : NULL;
|
return device ? (VMWSVGA_DEVICE*)device->DriverContext : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the display Get Mode operation.
|
|
||||||
static KSTATUS VmwSvgaDisplayGetMode(DISPLAY_DEVICE* device, DISPLAY_MODE* outMode) {
|
static KSTATUS VmwSvgaDisplayGetMode(DISPLAY_DEVICE* device, DISPLAY_MODE* outMode) {
|
||||||
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
||||||
if (!v || !outMode || !v->Framebuffer)
|
if (!v || !outMode || !v->Framebuffer)
|
||||||
@@ -840,7 +824,6 @@ static void VmwSvgaCopyToShadowAndFramebuffer(uint32_t* shadow,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the display pitched blit operation.
|
|
||||||
static KSTATUS VmwSvgaDisplayBlit(DISPLAY_DEVICE* device, int32_t x, int32_t y, int32_t w, int32_t h, const uint32_t* pixels, uint32_t pitchBytes) {
|
static KSTATUS VmwSvgaDisplayBlit(DISPLAY_DEVICE* device, int32_t x, int32_t y, int32_t w, int32_t h, const uint32_t* pixels, uint32_t pitchBytes) {
|
||||||
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
||||||
if (!v || !v->Backbuffer || !pixels || w <= 0 || h <= 0 ||
|
if (!v || !v->Backbuffer || !pixels || w <= 0 || h <= 0 ||
|
||||||
@@ -913,7 +896,6 @@ static KSTATUS VmwSvgaDisplayPresentPitched(DISPLAY_DEVICE* device,
|
|||||||
return VmwSvgaSyncDevice(v);
|
return VmwSvgaSyncDevice(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the display Fill Rect operation.
|
|
||||||
static KSTATUS VmwSvgaDisplayFillRect(DISPLAY_DEVICE* device, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) {
|
static KSTATUS VmwSvgaDisplayFillRect(DISPLAY_DEVICE* device, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) {
|
||||||
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
||||||
if (!v || !v->Backbuffer || w <= 0 || h <= 0)
|
if (!v || !v->Backbuffer || w <= 0 || h <= 0)
|
||||||
@@ -934,7 +916,6 @@ static KSTATUS VmwSvgaDisplayFillRect(DISPLAY_DEVICE* device, int32_t x, int32_t
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the display Copy Rect operation.
|
|
||||||
static KSTATUS VmwSvgaDisplayCopyRect(DISPLAY_DEVICE* device, int32_t dstX, int32_t dstY, int32_t srcX, int32_t srcY, int32_t w, int32_t h) {
|
static KSTATUS VmwSvgaDisplayCopyRect(DISPLAY_DEVICE* device, int32_t dstX, int32_t dstY, int32_t srcX, int32_t srcY, int32_t w, int32_t h) {
|
||||||
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
||||||
if (!v || !v->Backbuffer || w <= 0 || h <= 0)
|
if (!v || !v->Backbuffer || w <= 0 || h <= 0)
|
||||||
@@ -971,7 +952,6 @@ static KSTATUS VmwSvgaDisplayCopyRect(DISPLAY_DEVICE* device, int32_t dstX, int3
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the display Read Rect operation.
|
|
||||||
static KSTATUS VmwSvgaDisplayReadRect(DISPLAY_DEVICE* device, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t* outPixels, uint32_t outStride) {
|
static KSTATUS VmwSvgaDisplayReadRect(DISPLAY_DEVICE* device, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t* outPixels, uint32_t outStride) {
|
||||||
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
||||||
if (!v || !v->Backbuffer || !outPixels || outStride == 0 || w <= 0 || h <= 0)
|
if (!v || !v->Backbuffer || !outPixels || outStride == 0 || w <= 0 || h <= 0)
|
||||||
@@ -994,7 +974,6 @@ static KSTATUS VmwSvgaDisplayReadRect(DISPLAY_DEVICE* device, int32_t x, int32_t
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the display Present operation.
|
|
||||||
static KSTATUS VmwSvgaDisplayPresent(DISPLAY_DEVICE* device, const DISPLAY_RECT* rects, size_t rectCount) {
|
static KSTATUS VmwSvgaDisplayPresent(DISPLAY_DEVICE* device, const DISPLAY_RECT* rects, size_t rectCount) {
|
||||||
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
||||||
if (!v || !v->Framebuffer || !v->Backbuffer)
|
if (!v || !v->Framebuffer || !v->Backbuffer)
|
||||||
@@ -1039,13 +1018,11 @@ static KSTATUS VmwSvgaDisplayPresent(DISPLAY_DEVICE* device, const DISPLAY_RECT*
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the display Sync operation.
|
|
||||||
static KSTATUS VmwSvgaDisplaySync(DISPLAY_DEVICE* device) {
|
static KSTATUS VmwSvgaDisplaySync(DISPLAY_DEVICE* device) {
|
||||||
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
||||||
return VmwSvgaSyncDevice(v);
|
return VmwSvgaSyncDevice(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the display Set Cursor Image operation.
|
|
||||||
static KSTATUS VmwSvgaDisplaySetCursorImage(DISPLAY_DEVICE* device, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) {
|
static KSTATUS VmwSvgaDisplaySetCursorImage(DISPLAY_DEVICE* device, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) {
|
||||||
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
||||||
if (!v || !v->HardwareCursor)
|
if (!v || !v->HardwareCursor)
|
||||||
@@ -1053,7 +1030,6 @@ static KSTATUS VmwSvgaDisplaySetCursorImage(DISPLAY_DEVICE* device, int32_t widt
|
|||||||
return VmwSvgaDefineCursorImage(v, width, height, hotX, hotY, argbPixels);
|
return VmwSvgaDefineCursorImage(v, width, height, hotX, hotY, argbPixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the display Set Cursor Position operation.
|
|
||||||
static KSTATUS VmwSvgaDisplaySetCursorPosition(DISPLAY_DEVICE* device, int32_t x, int32_t y) {
|
static KSTATUS VmwSvgaDisplaySetCursorPosition(DISPLAY_DEVICE* device, int32_t x, int32_t y) {
|
||||||
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
||||||
if (!v)
|
if (!v)
|
||||||
@@ -1066,7 +1042,6 @@ static KSTATUS VmwSvgaDisplaySetCursorPosition(DISPLAY_DEVICE* device, int32_t x
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the restore Cursor operation.
|
|
||||||
static void VmwSvgaRestoreCursor(VMWSVGA_DEVICE* v) {
|
static void VmwSvgaRestoreCursor(VMWSVGA_DEVICE* v) {
|
||||||
if (!v || !v->CursorDrawn || !v->Backbuffer || !v->Framebuffer)
|
if (!v || !v->CursorDrawn || !v->Backbuffer || !v->Framebuffer)
|
||||||
return;
|
return;
|
||||||
@@ -1119,7 +1094,6 @@ static void VmwSvgaDrawCursor(VMWSVGA_DEVICE* v) {
|
|||||||
(void)VmwSvgaUpdate(v, dirty.X, dirty.Y, dirty.W, dirty.H);
|
(void)VmwSvgaUpdate(v, dirty.X, dirty.Y, dirty.W, dirty.H);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the display Show Cursor operation.
|
|
||||||
static KSTATUS VmwSvgaDisplayShowCursor(DISPLAY_DEVICE* device, bool show) {
|
static KSTATUS VmwSvgaDisplayShowCursor(DISPLAY_DEVICE* device, bool show) {
|
||||||
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
||||||
if (!v)
|
if (!v)
|
||||||
@@ -1154,7 +1128,6 @@ static KSTATUS VmwSvgaDisplayShowCursor(DISPLAY_DEVICE* device, bool show) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the display Query Stats operation.
|
|
||||||
static KSTATUS VmwSvgaDisplayQueryStats(DISPLAY_DEVICE* device, DISPLAY_STATS* outStats) {
|
static KSTATUS VmwSvgaDisplayQueryStats(DISPLAY_DEVICE* device, DISPLAY_STATS* outStats) {
|
||||||
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device);
|
||||||
if (!v || !outStats)
|
if (!v || !outStats)
|
||||||
@@ -1178,7 +1151,6 @@ static const DISPLAY_DEVICE_OPS gVmwSvgaDisplayOps = {
|
|||||||
.QueryStats = VmwSvgaDisplayQueryStats,
|
.QueryStats = VmwSvgaDisplayQueryStats,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements the select Bars operation.
|
|
||||||
static KSTATUS VmwSvgaSelectBars(VMWSVGA_DEVICE* v) {
|
static KSTATUS VmwSvgaSelectBars(VMWSVGA_DEVICE* v) {
|
||||||
PCI_BAR bar;
|
PCI_BAR bar;
|
||||||
memset(&bar, 0, sizeof(bar));
|
memset(&bar, 0, sizeof(bar));
|
||||||
@@ -1564,7 +1536,6 @@ KSTATUS VmwSvgaDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the add Device operation.
|
|
||||||
KSTATUS VmwSvgaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
KSTATUS VmwSvgaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
||||||
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -1589,14 +1560,12 @@ KSTATUS VmwSvgaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObj
|
|||||||
return NTLSTATUS_FAILURE;
|
return NTLSTATUS_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgPrint("VMWSVGA: FDO attached to %v\n", physicalDeviceObject->Name);
|
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
||||||
(void)module;
|
(void)module;
|
||||||
|
|
||||||
DbgPrint("VMWSVGA: driver loading...\n");
|
|
||||||
|
|
||||||
memset(&gVmwSvgaDriver, 0, sizeof(gVmwSvgaDriver));
|
memset(&gVmwSvgaDriver, 0, sizeof(gVmwSvgaDriver));
|
||||||
IoInitializeDriverObject(&gVmwSvgaDriver, SYS_SV_LITERAL("vmwaresvga"));
|
IoInitializeDriverObject(&gVmwSvgaDriver, SYS_SV_LITERAL("vmwaresvga"));
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
DIRS=ext4 fat ntfs
|
||||||
@@ -1130,7 +1130,8 @@ static void Ext4UnmountPartition(const IO_PARTITION_INFO* partition, IO_PARTITIO
|
|||||||
uint32_t count = gExt4MountedCount;
|
uint32_t count = gExt4MountedCount;
|
||||||
KeReleaseMutex(&gExt4MountMutex);
|
KeReleaseMutex(&gExt4MountMutex);
|
||||||
|
|
||||||
(void)IoRemoveVolume(ioVolume, IoVolumeBackingRemoved);
|
(void)IoRemoveVolume(ioVolume, change == IoPartitionSurpriseRemoved
|
||||||
|
? IoVolumeBackingRemoved : IoVolumeUnmounted);
|
||||||
IoReleaseVolume(ioVolume);
|
IoReleaseVolume(ioVolume);
|
||||||
DbgPrint("EXT4: disk=%u lba=%llu %s; unmounted volume=%u; total=%u\n",
|
DbgPrint("EXT4: disk=%u lba=%llu %s; unmounted volume=%u; total=%u\n",
|
||||||
partition->DiskIndex, (unsigned long long)partition->StartLba,
|
partition->DiskIndex, (unsigned long long)partition->StartLba,
|
||||||
@@ -1157,7 +1158,6 @@ static void Ext4PartitionChange(const IO_PARTITION_INFO* partition,
|
|||||||
|
|
||||||
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
||||||
(void)module;
|
(void)module;
|
||||||
DbgPrint("EXT4: Init\n");
|
|
||||||
|
|
||||||
Ext4ListInit(&gExt4Mounts);
|
Ext4ListInit(&gExt4Mounts);
|
||||||
gExt4MountedCount = 0;
|
gExt4MountedCount = 0;
|
||||||
@@ -1170,9 +1170,7 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gExt4MountedCount)
|
DbgPrint("fs: ext4 volumes=%u\n", gExt4MountedCount);
|
||||||
DbgPrint("EXT4: no mountable ext partitions found; driver resident for partition changes.\n");
|
|
||||||
DbgPrint("EXT4: Init complete; mounted %u volume(s).\n", gExt4MountedCount);
|
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
!include $(BASEDIR)\makefile.def
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
TARGETNAME=ext4
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=DRIVER
|
||||||
|
FLAVOR=EXT4
|
||||||
|
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib"
|
||||||
|
EXTRA_LFLAGS=/NOENTRY
|
||||||
|
INCLUDES=$(BASEDIR)\code\drivers\fs\ext4\include;$(BASEDIR)\code\drivers\fs\ext4\third_party\lwext4\include
|
||||||
|
SOURCES=@/code/drivers/fs/ext4/ext4_port.c @/code/drivers/fs/ext4/ext4_driver.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_balloc.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_bcache.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_bitmap.c \
|
||||||
|
@/code/drivers/fs/ext4/third_party/lwext4/src/ext4_block_group.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_blockdev.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_crc32.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_debug.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_dir.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_dir_idx.c \
|
||||||
|
@/code/drivers/fs/ext4/third_party/lwext4/src/ext4_extent.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_fs.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_hash.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_ialloc.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_inode.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_journal.c \
|
||||||
|
@/code/drivers/fs/ext4/third_party/lwext4/src/ext4_super.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_trans.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_xattr.c
|
||||||
@@ -98,7 +98,6 @@ static KSTATUS FatCacheRead(FAT_VOL* v, uint64_t lba, uint8_t** out) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the fat Cache Mark Dirty operation.
|
|
||||||
static void FatCacheMarkDirty(FAT_VOL* v, uint64_t lba) {
|
static void FatCacheMarkDirty(FAT_VOL* v, uint64_t lba) {
|
||||||
uint32_t slot = (uint32_t)(lba % FAT_CACHE_SLOTS);
|
uint32_t slot = (uint32_t)(lba % FAT_CACHE_SLOTS);
|
||||||
if (gFatCache[slot].valid && gFatCache[slot].vol == v && gFatCache[slot].lba == lba)
|
if (gFatCache[slot].valid && gFatCache[slot].vol == v && gFatCache[slot].lba == lba)
|
||||||
@@ -231,7 +230,6 @@ bool FatDirectoryNextSegment(FAT_VOL* v, uint32_t dirCluster,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the cluster To Lba operation.
|
|
||||||
uint64_t FatClusterToLba(FAT_VOL* v, uint32_t cluster) {
|
uint64_t FatClusterToLba(FAT_VOL* v, uint32_t cluster) {
|
||||||
return v->DataStart + (uint64_t)(cluster - 2) * v->SectorsPerCluster;
|
return v->DataStart + (uint64_t)(cluster - 2) * v->SectorsPerCluster;
|
||||||
}
|
}
|
||||||
@@ -390,12 +388,10 @@ void FatFreeClusterChain(FAT_VOL* v, uint32_t start) {
|
|||||||
|
|
||||||
// FAT timestamp and DIRENT metadata helpers.
|
// FAT timestamp and DIRENT metadata helpers.
|
||||||
|
|
||||||
// Implements the fat Is Leap Year operation.
|
|
||||||
static bool FatIsLeapYear(uint32_t year) {
|
static bool FatIsLeapYear(uint32_t year) {
|
||||||
return ((year % 4u) == 0u && (year % 100u) != 0u) || ((year % 400u) == 0u);
|
return ((year % 4u) == 0u && (year % 100u) != 0u) || ((year % 400u) == 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the fat Days In Month operation.
|
|
||||||
static uint32_t FatDaysInMonth(uint32_t year, uint32_t month) {
|
static uint32_t FatDaysInMonth(uint32_t year, uint32_t month) {
|
||||||
static const uint8_t days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
|
static const uint8_t days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
|
||||||
if (month < 1u || month > 12u) return 31u;
|
if (month < 1u || month > 12u) return 31u;
|
||||||
@@ -414,13 +410,11 @@ static uint64_t FatCalendarToEpochSeconds(uint32_t year, uint32_t month, uint32_
|
|||||||
return (((days * 24u) + hour) * 60u + minute) * 60u + second;
|
return (((days * 24u) + hour) * 60u + minute) * 60u + second;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the fat Day Of Week operation.
|
|
||||||
static uint8_t FatDayOfWeek(uint32_t year, uint32_t month, uint32_t day) {
|
static uint8_t FatDayOfWeek(uint32_t year, uint32_t month, uint32_t day) {
|
||||||
uint64_t epoch = FatCalendarToEpochSeconds(year, month, day, 0, 0, 0);
|
uint64_t epoch = FatCalendarToEpochSeconds(year, month, day, 0, 0, 0);
|
||||||
return (uint8_t)(((epoch / 86400u) + 4u) % 7u);
|
return (uint8_t)(((epoch / 86400u) + 4u) % 7u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the fat Encode Date operation.
|
|
||||||
static uint16_t FatEncodeDate(const SYS_SYSTEM_TIME* t) {
|
static uint16_t FatEncodeDate(const SYS_SYSTEM_TIME* t) {
|
||||||
uint32_t year = t && t->Year ? t->Year : 1980u;
|
uint32_t year = t && t->Year ? t->Year : 1980u;
|
||||||
uint32_t month = t && t->Month ? t->Month : 1u;
|
uint32_t month = t && t->Month ? t->Month : 1u;
|
||||||
@@ -435,7 +429,6 @@ static uint16_t FatEncodeDate(const SYS_SYSTEM_TIME* t) {
|
|||||||
return (uint16_t)(((year - 1980u) << 9) | (month << 5) | day);
|
return (uint16_t)(((year - 1980u) << 9) | (month << 5) | day);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the fat Encode Time operation.
|
|
||||||
static uint16_t FatEncodeTime(const SYS_SYSTEM_TIME* t) {
|
static uint16_t FatEncodeTime(const SYS_SYSTEM_TIME* t) {
|
||||||
uint32_t hour = t ? t->Hour : 0u;
|
uint32_t hour = t ? t->Hour : 0u;
|
||||||
uint32_t minute = t ? t->Minute : 0u;
|
uint32_t minute = t ? t->Minute : 0u;
|
||||||
@@ -446,7 +439,6 @@ static uint16_t FatEncodeTime(const SYS_SYSTEM_TIME* t) {
|
|||||||
return (uint16_t)((hour << 11) | (minute << 5) | (second / 2u));
|
return (uint16_t)((hour << 11) | (minute << 5) | (second / 2u));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the fat Encode Create Time Tenth operation.
|
|
||||||
static uint8_t FatEncodeCreateTimeTenth(const SYS_SYSTEM_TIME* t) {
|
static uint8_t FatEncodeCreateTimeTenth(const SYS_SYSTEM_TIME* t) {
|
||||||
uint32_t second = t ? t->Second : 0u;
|
uint32_t second = t ? t->Second : 0u;
|
||||||
uint32_t ms = t ? t->Millisecond : 0u;
|
uint32_t ms = t ? t->Millisecond : 0u;
|
||||||
@@ -457,7 +449,6 @@ static uint8_t FatEncodeCreateTimeTenth(const SYS_SYSTEM_TIME* t) {
|
|||||||
return (uint8_t)v;
|
return (uint8_t)v;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the fat Query Encoded Time operation.
|
|
||||||
void FatQueryEncodedTime(FAT_ENCODED_TIME* out) {
|
void FatQueryEncodedTime(FAT_ENCODED_TIME* out) {
|
||||||
SYS_SYSTEM_TIME now;
|
SYS_SYSTEM_TIME now;
|
||||||
memset(&now, 0, sizeof(now));
|
memset(&now, 0, sizeof(now));
|
||||||
@@ -502,7 +493,6 @@ void FatDecodeDateTime(uint16_t date, uint16_t time, uint8_t createTenth,
|
|||||||
out->EpochSeconds = FatCalendarToEpochSeconds(year, month, day, hour, minute, second);
|
out->EpochSeconds = FatCalendarToEpochSeconds(year, month, day, hour, minute, second);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the fat Decode Access Date operation.
|
|
||||||
void FatDecodeAccessDate(uint16_t date, SYS_SYSTEM_TIME* out) {
|
void FatDecodeAccessDate(uint16_t date, SYS_SYSTEM_TIME* out) {
|
||||||
FatDecodeDateTime(date, 0, 0, out);
|
FatDecodeDateTime(date, 0, 0, out);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ static volatile int gFatAsyncInitState;
|
|||||||
static void FatAsyncReadSubmitNext(FAT_ASYNC_RW* ctx);
|
static void FatAsyncReadSubmitNext(FAT_ASYNC_RW* ctx);
|
||||||
static void FatAsyncWriteSubmitNext(FAT_ASYNC_RW* ctx);
|
static void FatAsyncWriteSubmitNext(FAT_ASYNC_RW* ctx);
|
||||||
|
|
||||||
// Implements the async Worker operation.
|
|
||||||
static void FatAsyncWorker(void* arg) {
|
static void FatAsyncWorker(void* arg) {
|
||||||
(void)arg;
|
(void)arg;
|
||||||
|
|
||||||
@@ -70,7 +69,6 @@ static void FatAsyncWorker(void* arg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ensure Async Worker Started operation.
|
|
||||||
static KSTATUS FatEnsureAsyncWorkerStarted(void) {
|
static KSTATUS FatEnsureAsyncWorkerStarted(void) {
|
||||||
uintptr_t flags = KeAcquireSpinlock(&gFatAsyncLock);
|
uintptr_t flags = KeAcquireSpinlock(&gFatAsyncLock);
|
||||||
if (gFatAsyncInitState == 2) {
|
if (gFatAsyncInitState == 2) {
|
||||||
@@ -104,7 +102,6 @@ static KSTATUS FatEnsureAsyncWorkerStarted(void) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the async Queue Continuation operation.
|
|
||||||
static void FatAsyncQueueContinuation(FAT_ASYNC_RW* ctx) {
|
static void FatAsyncQueueContinuation(FAT_ASYNC_RW* ctx) {
|
||||||
if (!ctx) return;
|
if (!ctx) return;
|
||||||
|
|
||||||
@@ -114,7 +111,6 @@ static void FatAsyncQueueContinuation(FAT_ASYNC_RW* ctx) {
|
|||||||
KeSignalSemaphore(gFatAsyncSemaphore);
|
KeSignalSemaphore(gFatAsyncSemaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the async Finish operation.
|
|
||||||
static void FatAsyncFinish(FAT_ASYNC_RW* ctx, KSTATUS status, size_t information) {
|
static void FatAsyncFinish(FAT_ASYNC_RW* ctx, KSTATUS status, size_t information) {
|
||||||
if (!ctx) return;
|
if (!ctx) return;
|
||||||
if (ctx->CurrentDevice) {
|
if (ctx->CurrentDevice) {
|
||||||
@@ -128,7 +124,6 @@ static void FatAsyncFinish(FAT_ASYNC_RW* ctx, KSTATUS status, size_t information
|
|||||||
if (complete) complete(completeContext, status, information);
|
if (complete) complete(completeContext, status, information);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the async Read Irp Complete operation.
|
|
||||||
static void FatAsyncReadIrpComplete(IRP* irp, void* completeCtx) {
|
static void FatAsyncReadIrpComplete(IRP* irp, void* completeCtx) {
|
||||||
FAT_ASYNC_RW* ctx = (FAT_ASYNC_RW*)completeCtx;
|
FAT_ASYNC_RW* ctx = (FAT_ASYNC_RW*)completeCtx;
|
||||||
if (!ctx) return;
|
if (!ctx) return;
|
||||||
@@ -158,7 +153,6 @@ static void FatAsyncReadIrpComplete(IRP* irp, void* completeCtx) {
|
|||||||
FatAsyncQueueContinuation(ctx);
|
FatAsyncQueueContinuation(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the async Read Submit Next operation.
|
|
||||||
static void FatAsyncReadSubmitNext(FAT_ASYNC_RW* ctx) {
|
static void FatAsyncReadSubmitNext(FAT_ASYNC_RW* ctx) {
|
||||||
if (ctx->Remaining == 0) {
|
if (ctx->Remaining == 0) {
|
||||||
FatAsyncFinish(ctx, NTLSTATUS_SUCCESS, ctx->Done);
|
FatAsyncFinish(ctx, NTLSTATUS_SUCCESS, ctx->Done);
|
||||||
@@ -271,7 +265,6 @@ KSTATUS FatReadAsync(IO_VOLUME_PROVIDER* fs, void* fileCtx,
|
|||||||
return NTLSTATUS_PENDING;
|
return NTLSTATUS_PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the async Write Irp Complete operation.
|
|
||||||
static void FatAsyncWriteIrpComplete(IRP* irp, void* completeCtx) {
|
static void FatAsyncWriteIrpComplete(IRP* irp, void* completeCtx) {
|
||||||
FAT_ASYNC_RW* ctx = (FAT_ASYNC_RW*)completeCtx;
|
FAT_ASYNC_RW* ctx = (FAT_ASYNC_RW*)completeCtx;
|
||||||
if (!ctx) return;
|
if (!ctx) return;
|
||||||
@@ -294,7 +287,6 @@ static void FatAsyncWriteIrpComplete(IRP* irp, void* completeCtx) {
|
|||||||
FatAsyncQueueContinuation(ctx);
|
FatAsyncQueueContinuation(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the async Write Submit Next operation.
|
|
||||||
static void FatAsyncWriteSubmitNext(FAT_ASYNC_RW* ctx) {
|
static void FatAsyncWriteSubmitNext(FAT_ASYNC_RW* ctx) {
|
||||||
if (ctx->Remaining == 0) {
|
if (ctx->Remaining == 0) {
|
||||||
uint64_t newEnd = ctx->Offset + ctx->Done;
|
uint64_t newEnd = ctx->Offset + ctx->Done;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ static char FatUpperChar(char c);
|
|||||||
static bool FatIsLowerChar(char c);
|
static bool FatIsLowerChar(char c);
|
||||||
static bool FatIsValidShortChar(char c);
|
static bool FatIsValidShortChar(char c);
|
||||||
|
|
||||||
// Implements the make83 Name V operation.
|
|
||||||
static void Make83NameV(SYS_STRING_VIEW src, char name8[8], char ext3[3]) {
|
static void Make83NameV(SYS_STRING_VIEW src, char name8[8], char ext3[3]) {
|
||||||
memset(name8, ' ', 8);
|
memset(name8, ' ', 8);
|
||||||
memset(ext3, ' ', 3);
|
memset(ext3, ' ', 3);
|
||||||
@@ -48,17 +47,14 @@ static void Make83NameV(SYS_STRING_VIEW src, char name8[8], char ext3[3]) {
|
|||||||
|
|
||||||
// LFN assembly / matching.
|
// LFN assembly / matching.
|
||||||
|
|
||||||
// Implements the fat Upper Char operation.
|
|
||||||
static char FatUpperChar(char c) {
|
static char FatUpperChar(char c) {
|
||||||
return (c >= 'a' && c <= 'z') ? (char)(c - 32) : c;
|
return (c >= 'a' && c <= 'z') ? (char)(c - 32) : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the fat Is Lower Char operation.
|
|
||||||
static bool FatIsLowerChar(char c) {
|
static bool FatIsLowerChar(char c) {
|
||||||
return c >= 'a' && c <= 'z';
|
return c >= 'a' && c <= 'z';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the fat Is Valid Short Char operation.
|
|
||||||
static bool FatIsValidShortChar(char c) {
|
static bool FatIsValidShortChar(char c) {
|
||||||
c = FatUpperChar(c);
|
c = FatUpperChar(c);
|
||||||
if (c >= 'A' && c <= 'Z') return true;
|
if (c >= 'A' && c <= 'Z') return true;
|
||||||
@@ -96,14 +92,12 @@ static bool FatNameIsStructurallyShort83V(SYS_STRING_VIEW name) {
|
|||||||
return baseLen >= 1 && baseLen <= 8 && extLen <= 3;
|
return baseLen >= 1 && baseLen <= 8 && extLen <= 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the fat Component Has Lower V operation.
|
|
||||||
static bool FatComponentHasLowerV(SYS_STRING_VIEW name, size_t start, size_t end) {
|
static bool FatComponentHasLowerV(SYS_STRING_VIEW name, size_t start, size_t end) {
|
||||||
for (size_t i = start; i < end; i++)
|
for (size_t i = start; i < end; i++)
|
||||||
if (FatIsLowerChar(name.Data[i])) return true;
|
if (FatIsLowerChar(name.Data[i])) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the fat Component Has Upper V operation.
|
|
||||||
static bool FatComponentHasUpperV(SYS_STRING_VIEW name, size_t start, size_t end) {
|
static bool FatComponentHasUpperV(SYS_STRING_VIEW name, size_t start, size_t end) {
|
||||||
for (size_t i = start; i < end; i++)
|
for (size_t i = start; i < end; i++)
|
||||||
if (name.Data[i] >= 'A' && name.Data[i] <= 'Z') return true;
|
if (name.Data[i] >= 'A' && name.Data[i] <= 'Z') return true;
|
||||||
@@ -144,7 +138,6 @@ static bool FatNameNeedsLfnForCreateV(SYS_STRING_VIEW name) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the fat Short Name Case Flags V operation.
|
|
||||||
static uint8_t FatShortNameCaseFlagsV(SYS_STRING_VIEW name) {
|
static uint8_t FatShortNameCaseFlagsV(SYS_STRING_VIEW name) {
|
||||||
if (!FatNameIsStructurallyShort83V(name)) return 0;
|
if (!FatNameIsStructurallyShort83V(name)) return 0;
|
||||||
size_t baseEnd, extStart, extEnd;
|
size_t baseEnd, extStart, extEnd;
|
||||||
@@ -160,7 +153,6 @@ static uint8_t FatShortNameCaseFlagsV(SYS_STRING_VIEW name) {
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the lfn Checksum operation.
|
|
||||||
static uint8_t LfnChecksum(const char name8[8], const char ext3[3]) {
|
static uint8_t LfnChecksum(const char name8[8], const char ext3[3]) {
|
||||||
uint8_t sum = 0;
|
uint8_t sum = 0;
|
||||||
for (int i = 0; i < 11; i++) {
|
for (int i = 0; i < 11; i++) {
|
||||||
@@ -170,7 +162,6 @@ static uint8_t LfnChecksum(const char name8[8], const char ext3[3]) {
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the lfn Set Char operation.
|
|
||||||
static void LfnSetChar(LFN_ENTRY* e, int idx, uint16_t value) {
|
static void LfnSetChar(LFN_ENTRY* e, int idx, uint16_t value) {
|
||||||
if (idx < 5) e->Name1[idx] = value;
|
if (idx < 5) e->Name1[idx] = value;
|
||||||
else if (idx < 11) e->Name2[idx - 5] = value;
|
else if (idx < 11) e->Name2[idx - 5] = value;
|
||||||
@@ -242,7 +233,6 @@ static bool ShortNameExistsRaw(FAT_VOL* v, uint32_t dirCluster,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the fat Alias Append Char operation.
|
|
||||||
static void FatAliasAppendChar(char* dst, int* len, int maxLen, char c) {
|
static void FatAliasAppendChar(char* dst, int* len, int maxLen, char c) {
|
||||||
c = FatUpperChar(c);
|
c = FatUpperChar(c);
|
||||||
if (!FatIsValidShortChar(c)) return;
|
if (!FatIsValidShortChar(c)) return;
|
||||||
@@ -384,7 +374,6 @@ static KSTATUS DeleteLegacyBrokenDotAliasV(FAT_VOL* v, uint32_t dirCluster,
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the lfn Append operation.
|
|
||||||
void FatLfnAppend(char* lfn, const LFN_ENTRY* e) {
|
void FatLfnAppend(char* lfn, const LFN_ENTRY* e) {
|
||||||
int seq = (e->Order & 0x3F) - 1;
|
int seq = (e->Order & 0x3F) - 1;
|
||||||
if (seq < 0 || seq >= (FAT_MAX_LFN / 13)) return;
|
if (seq < 0 || seq >= (FAT_MAX_LFN / 13)) return;
|
||||||
@@ -413,7 +402,6 @@ static bool FatStringViewDataIsPlausible(SYS_STRING_VIEW view) {
|
|||||||
return data >= 0x10000u;
|
return data >= 0x10000u;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the name View Is Valid operation.
|
|
||||||
static bool FatNameViewIsValid(SYS_STRING_VIEW name) {
|
static bool FatNameViewIsValid(SYS_STRING_VIEW name) {
|
||||||
if (!FatStringViewDataIsPlausible(name)) return false;
|
if (!FatStringViewDataIsPlausible(name)) return false;
|
||||||
if (name.Length == 0 || name.Length >= FAT_MAX_LFN) return false;
|
if (name.Length == 0 || name.Length >= FAT_MAX_LFN) return false;
|
||||||
@@ -424,7 +412,6 @@ static bool FatNameViewIsValid(SYS_STRING_VIEW name) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the lfn Match V operation.
|
|
||||||
static bool LfnMatchV(const char* lfn, SYS_STRING_VIEW want) {
|
static bool LfnMatchV(const char* lfn, SYS_STRING_VIEW want) {
|
||||||
if (!lfn || !SysSvIsValid(want)) return false;
|
if (!lfn || !SysSvIsValid(want)) return false;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|||||||
@@ -249,7 +249,8 @@ static void FatUnmountPartition(const IO_PARTITION_INFO* partition, IO_PARTITION
|
|||||||
uint32_t mountedCount = gMountedCount;
|
uint32_t mountedCount = gMountedCount;
|
||||||
KeReleaseMutex(&gFatMountMutex);
|
KeReleaseMutex(&gFatMountMutex);
|
||||||
|
|
||||||
(void)IoRemoveVolume(volume, IoVolumeBackingRemoved);
|
(void)IoRemoveVolume(volume, change == IoPartitionSurpriseRemoved
|
||||||
|
? IoVolumeBackingRemoved : IoVolumeUnmounted);
|
||||||
IoReleaseVolume(volume); // Drop the active mount-list reference.
|
IoReleaseVolume(volume); // Drop the active mount-list reference.
|
||||||
DbgPrint("FAT: disk=%u lba=%llu %s; unmounted volume=%u; total=%u\n",
|
DbgPrint("FAT: disk=%u lba=%llu %s; unmounted volume=%u; total=%u\n",
|
||||||
partition->DiskIndex, (unsigned long long)partition->StartLba,
|
partition->DiskIndex, (unsigned long long)partition->StartLba,
|
||||||
@@ -278,7 +279,6 @@ static void FatPartitionChange(const IO_PARTITION_INFO* partition,
|
|||||||
// Initializes FAT and subscribes to the authoritative kernel partition stream.
|
// Initializes FAT and subscribes to the authoritative kernel partition stream.
|
||||||
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
||||||
(void)module;
|
(void)module;
|
||||||
DbgPrint("FAT: Init\n");
|
|
||||||
|
|
||||||
|
|
||||||
FatCacheInvalidate();
|
FatCacheInvalidate();
|
||||||
@@ -292,9 +292,7 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gMountedCount)
|
DbgPrint("fs: fat volumes=%u\n", gMountedCount);
|
||||||
DbgPrint("FAT: no mountable FAT partitions found; driver resident for partition changes.\n");
|
|
||||||
DbgPrint("FAT: Init complete; mounted %u volume(s).\n", gMountedCount);
|
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
!include $(BASEDIR)\makefile.def
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
TARGETNAME=fat
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=DRIVER
|
||||||
|
FLAVOR=DRIVER
|
||||||
|
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib"
|
||||||
|
EXTRA_LFLAGS=/NOENTRY
|
||||||
|
SOURCES=@/code/drivers/fs/fat/fat.c @/code/drivers/fs/fat/fat_directory.c @/code/drivers/fs/fat/fat_file.c @/code/drivers/fs/fat/fat_async.c @/code/drivers/fs/fat/fat_driver.c @/code/drivers/fs/fat/fat_mount.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DIRS=ntfs3g
|
||||||
@@ -1571,7 +1571,8 @@ static void NtfsUnmountPartition(const IO_PARTITION_INFO* partition, IO_PARTITIO
|
|||||||
uint32_t mountedCount = gMountedCount;
|
uint32_t mountedCount = gMountedCount;
|
||||||
KeReleaseMutex(&gNtfsMountMutex);
|
KeReleaseMutex(&gNtfsMountMutex);
|
||||||
|
|
||||||
(void)IoRemoveVolume(volume, IoVolumeBackingRemoved);
|
(void)IoRemoveVolume(volume, change == IoPartitionSurpriseRemoved
|
||||||
|
? IoVolumeBackingRemoved : IoVolumeUnmounted);
|
||||||
IoReleaseVolume(volume); // Drop the active mount-list reference.
|
IoReleaseVolume(volume); // Drop the active mount-list reference.
|
||||||
DbgPrint("NTFS: disk=%u lba=%llu %s; unmounted volume=%u; total=%u\n",
|
DbgPrint("NTFS: disk=%u lba=%llu %s; unmounted volume=%u; total=%u\n",
|
||||||
partition->DiskIndex, (unsigned long long)partition->StartLba,
|
partition->DiskIndex, (unsigned long long)partition->StartLba,
|
||||||
@@ -1600,7 +1601,6 @@ static void NtfsPartitionChange(const IO_PARTITION_INFO* partition,
|
|||||||
// Initializes NTFS and subscribes to the authoritative kernel partition stream.
|
// Initializes NTFS and subscribes to the authoritative kernel partition stream.
|
||||||
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
||||||
(void)module;
|
(void)module;
|
||||||
DbgPrint("NTFS: Init\n");
|
|
||||||
|
|
||||||
|
|
||||||
LIST_INIT(&gNtfsMounts);
|
LIST_INIT(&gNtfsMounts);
|
||||||
@@ -1613,9 +1613,7 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gMountedCount)
|
DbgPrint("fs: ntfs volumes=%u\n", gMountedCount);
|
||||||
DbgPrint("NTFS: no mountable NTFS partitions found; driver resident for partition changes.\n");
|
|
||||||
DbgPrint("NTFS: Init complete; mounted %u volume(s).\n", gMountedCount);
|
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
!include $(BASEDIR)\makefile.def
|
||||||
@@ -1114,7 +1114,8 @@ static void Ntfs3gUnmountPartition(const IO_PARTITION_INFO* partition, IO_PARTIT
|
|||||||
uint32_t count = gNtfs3gMountedCount;
|
uint32_t count = gNtfs3gMountedCount;
|
||||||
KeReleaseMutex(&gNtfs3gMountMutex);
|
KeReleaseMutex(&gNtfs3gMountMutex);
|
||||||
|
|
||||||
(void)IoRemoveVolume(ioVolume, IoVolumeBackingRemoved);
|
(void)IoRemoveVolume(ioVolume, change == IoPartitionSurpriseRemoved
|
||||||
|
? IoVolumeBackingRemoved : IoVolumeUnmounted);
|
||||||
IoReleaseVolume(ioVolume);
|
IoReleaseVolume(ioVolume);
|
||||||
DbgPrint("NTFS3G: disk=%u lba=%llu %s; unmounted volume=%u; total=%u\n",
|
DbgPrint("NTFS3G: disk=%u lba=%llu %s; unmounted volume=%u; total=%u\n",
|
||||||
partition->DiskIndex, (unsigned long long)partition->StartLba,
|
partition->DiskIndex, (unsigned long long)partition->StartLba,
|
||||||
@@ -1140,14 +1141,13 @@ static void Ntfs3gPartitionChange(const IO_PARTITION_INFO* partition,
|
|||||||
|
|
||||||
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
||||||
(void)module;
|
(void)module;
|
||||||
DbgPrint("NTFS3G: Init (libntfs-3g replacement driver)\n");
|
|
||||||
Ntfs3gListInit(&gNtfs3gMounts);
|
Ntfs3gListInit(&gNtfs3gMounts);
|
||||||
gNtfs3gMountedCount = 0;
|
gNtfs3gMountedCount = 0;
|
||||||
Ntfs3gEnsureMutexes();
|
Ntfs3gEnsureMutexes();
|
||||||
KSTATUS status = IoRegisterPartitionChangeCallback(Ntfs3gPartitionChange, (void*)0);
|
KSTATUS status = IoRegisterPartitionChangeCallback(Ntfs3gPartitionChange, (void*)0);
|
||||||
if (!KSUCCESS(status))
|
if (!KSUCCESS(status))
|
||||||
return status;
|
return status;
|
||||||
DbgPrint("NTFS3G: Init complete; mounted %u volume(s).\n", gNtfs3gMountedCount);
|
DbgPrint("fs: ntfs3g volumes=%u\n", gNtfs3gMountedCount);
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
TARGETNAME=ntfs
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=DRIVER
|
||||||
|
FLAVOR=NTFS
|
||||||
|
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\printf.lib"
|
||||||
|
EXTRA_LFLAGS=/NOENTRY
|
||||||
|
INCLUDES=$(BASEDIR)\code\drivers\fs\ntfs\ntfs3g\include;$(BASEDIR)\code\drivers\fs\ntfs\ntfs3g\third_party\ntfs-3g\include;$(BASEDIR)\code\drivers\fs\ntfs\ntfs3g\third_party\ntfs-3g\include\ntfs-3g
|
||||||
|
SOURCES=@/code/drivers/fs/ntfs/ntfs3g/ntfs3g_port.c @/code/drivers/fs/ntfs/ntfs3g/ntfs3g_device.c @/code/drivers/fs/ntfs/ntfs3g/ntfs3g_driver.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/acls.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/attrib.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/attrlist.c \
|
||||||
|
@/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/bitmap.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/bootsect.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/cache.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/collate.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/compat.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/compress.c \
|
||||||
|
@/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/debug.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/device.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/dir.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/ea.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/efs.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/index.c \
|
||||||
|
@/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/inode.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/ioctl.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/lcnalloc.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/logfile.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/logging.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/mft.c \
|
||||||
|
@/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/misc.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/mst.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/object_id.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/realpath.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/reparse.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/runlist.c \
|
||||||
|
@/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/security.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/unistr.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/volume.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/xattrs.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DIRS=ps2 serial
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!include $(BASEDIR)\makefile.def
|
||||||
@@ -4,6 +4,8 @@
|
|||||||
#include "ps2.h"
|
#include "ps2.h"
|
||||||
|
|
||||||
static KDPC gKeyboardDpc;
|
static KDPC gKeyboardDpc;
|
||||||
|
static KE_INTERRUPT* gKeyboardInterrupt;
|
||||||
|
static KE_INTERRUPT* gMouseInterrupt;
|
||||||
static KDPC gMouseDpc;
|
static KDPC gMouseDpc;
|
||||||
static volatile bool gKeyboardNextExtended;
|
static volatile bool gKeyboardNextExtended;
|
||||||
static INPUT_KEY_EVENT gKeyboardDpcQueue[KEYBOARD_DPC_QUEUE_SIZE];
|
static INPUT_KEY_EVENT gKeyboardDpcQueue[KEYBOARD_DPC_QUEUE_SIZE];
|
||||||
@@ -24,7 +26,6 @@ static volatile uint32_t gMousePacketCount;
|
|||||||
static volatile uint32_t gKeyboardForeignIrqCount;
|
static volatile uint32_t gKeyboardForeignIrqCount;
|
||||||
static volatile uint32_t gMouseForeignIrqCount;
|
static volatile uint32_t gMouseForeignIrqCount;
|
||||||
|
|
||||||
// Implements the ps2 Set1 To Key operation.
|
|
||||||
static INPUT_KEY Ps2Set1ToKey(uint8_t make, bool extended) {
|
static INPUT_KEY Ps2Set1ToKey(uint8_t make, bool extended) {
|
||||||
if (extended) {
|
if (extended) {
|
||||||
switch (make) {
|
switch (make) {
|
||||||
@@ -135,7 +136,6 @@ static INPUT_KEY Ps2Set1ToKey(uint8_t make, bool extended) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Keyboard Dpc Routine operation.
|
|
||||||
static void Ps2KeyboardDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2) {
|
static void Ps2KeyboardDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2) {
|
||||||
(void)dpc;
|
(void)dpc;
|
||||||
(void)context;
|
(void)context;
|
||||||
@@ -147,13 +147,12 @@ static void Ps2KeyboardDpcRoutine(KDPC* dpc, void* context, void* systemArgument
|
|||||||
gKeyboardDpcHead = (gKeyboardDpcHead + 1) & (int)KEYBOARD_DPC_QUEUE_MASK;
|
gKeyboardDpcHead = (gKeyboardDpcHead + 1) & (int)KEYBOARD_DPC_QUEUE_MASK;
|
||||||
KeInputSubmitKey(&event);
|
KeInputSubmitKey(&event);
|
||||||
uint32_t n = ++gKeyboardEventCount;
|
uint32_t n = ++gKeyboardEventCount;
|
||||||
if ((n & (n - 1u)) == 0u)
|
// if ((n & (n - 1u)) == 0u)
|
||||||
DbgPrint("ps2: keyboard progress irq=%u raw=%u events=%u foreign=%u\n",
|
// DbgPrint("ps2: keyboard progress irq=%u raw=%u events=%u foreign=%u\n",
|
||||||
gKeyboardIrqCount, gKeyboardByteCount, n, gKeyboardForeignIrqCount);
|
// gKeyboardIrqCount, gKeyboardByteCount, n, gKeyboardForeignIrqCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Queue Keyboard Event operation.
|
|
||||||
static void Ps2QueueKeyboardEvent(INPUT_KEY key, bool pressed) {
|
static void Ps2QueueKeyboardEvent(INPUT_KEY key, bool pressed) {
|
||||||
if (key >= sizeof(gKeyboardDown))
|
if (key >= sizeof(gKeyboardDown))
|
||||||
return;
|
return;
|
||||||
@@ -173,8 +172,8 @@ static void Ps2QueueKeyboardEvent(INPUT_KEY key, bool pressed) {
|
|||||||
KeInsertQueueDpc(&gKeyboardDpc, 0, 0);
|
KeInsertQueueDpc(&gKeyboardDpc, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Keyboard Isr operation.
|
static void Ps2KeyboardIsr(void* context) {
|
||||||
static void Ps2KeyboardIsr(void) {
|
(void)context;
|
||||||
++gKeyboardIrqCount;
|
++gKeyboardIrqCount;
|
||||||
uint8_t status = __inbyte(PS2_STAT);
|
uint8_t status = __inbyte(PS2_STAT);
|
||||||
// The 8042 output buffer is shared; never consume AUX bytes as scancodes.
|
// The 8042 output buffer is shared; never consume AUX bytes as scancodes.
|
||||||
@@ -200,7 +199,6 @@ static void Ps2KeyboardIsr(void) {
|
|||||||
Ps2QueueKeyboardEvent(key, !released);
|
Ps2QueueKeyboardEvent(key, !released);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Mouse Dpc Routine operation.
|
|
||||||
static void Ps2MouseDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2) {
|
static void Ps2MouseDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2) {
|
||||||
(void)dpc;
|
(void)dpc;
|
||||||
(void)context;
|
(void)context;
|
||||||
@@ -219,14 +217,14 @@ static void Ps2MouseDpcRoutine(KDPC* dpc, void* context, void* systemArgument1,
|
|||||||
};
|
};
|
||||||
KeInputSubmitMouse(&event);
|
KeInputSubmitMouse(&event);
|
||||||
uint32_t n = ++gMousePacketCount;
|
uint32_t n = ++gMousePacketCount;
|
||||||
if ((n & (n - 1u)) == 0u)
|
// if ((n & (n - 1u)) == 0u)
|
||||||
DbgPrint("ps2: mouse progress irq=%u raw=%u packets=%u foreign=%u\n",
|
// DbgPrint("ps2: mouse progress irq=%u raw=%u packets=%u foreign=%u\n",
|
||||||
gMouseIrqCount, gMouseByteCount, n, gMouseForeignIrqCount);
|
// gMouseIrqCount, gMouseByteCount, n, gMouseForeignIrqCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Mouse Isr operation.
|
static void Ps2MouseIsr(void* context) {
|
||||||
static void Ps2MouseIsr(void) {
|
(void)context;
|
||||||
++gMouseIrqCount;
|
++gMouseIrqCount;
|
||||||
uint8_t status = __inbyte(PS2_STAT);
|
uint8_t status = __inbyte(PS2_STAT);
|
||||||
if (!(status & PS2_STAT_OUT_FULL) || !(status & PS2_STAT_AUX_DATA)) {
|
if (!(status & PS2_STAT_OUT_FULL) || !(status & PS2_STAT_AUX_DATA)) {
|
||||||
@@ -262,7 +260,6 @@ static void Ps2MouseIsr(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Controller Prepare operation.
|
|
||||||
static void Ps2ControllerPrepare(void) {
|
static void Ps2ControllerPrepare(void) {
|
||||||
Ps2WriteCommand(0xADu); // disable keyboard port
|
Ps2WriteCommand(0xADu); // disable keyboard port
|
||||||
Ps2WriteCommand(0xA7u); // disable aux port
|
Ps2WriteCommand(0xA7u); // disable aux port
|
||||||
@@ -281,7 +278,6 @@ static void Ps2ControllerPrepare(void) {
|
|||||||
Ps2FlushOutput();
|
Ps2FlushOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Controller Enable Interrupts operation.
|
|
||||||
static void Ps2ControllerEnableInterrupts(void) {
|
static void Ps2ControllerEnableInterrupts(void) {
|
||||||
uint8_t commandByte = Ps2ReadCommandByte();
|
uint8_t commandByte = Ps2ReadCommandByte();
|
||||||
commandByte |= 0x01u;
|
commandByte |= 0x01u;
|
||||||
@@ -289,7 +285,6 @@ static void Ps2ControllerEnableInterrupts(void) {
|
|||||||
Ps2WriteCommandByte(commandByte);
|
Ps2WriteCommandByte(commandByte);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Keyboard Initialize operation.
|
|
||||||
static void Ps2KeyboardInitialize(void) {
|
static void Ps2KeyboardInitialize(void) {
|
||||||
// Enable scanning. If the keyboard is absent, the timeout/ACK failure is
|
// Enable scanning. If the keyboard is absent, the timeout/ACK failure is
|
||||||
// non-fatal; the IRQ path simply never produces events.
|
// non-fatal; the IRQ path simply never produces events.
|
||||||
@@ -297,7 +292,6 @@ static void Ps2KeyboardInitialize(void) {
|
|||||||
DbgPrint("ps2: keyboard enable did not ACK\n");
|
DbgPrint("ps2: keyboard enable did not ACK\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Mouse Initialize operation.
|
|
||||||
static void Ps2MouseInitialize(void) {
|
static void Ps2MouseInitialize(void) {
|
||||||
if (!Ps2SendMouse(0xFFu)) {
|
if (!Ps2SendMouse(0xFFu)) {
|
||||||
DbgPrint("ps2: mouse reset did not ACK\n");
|
DbgPrint("ps2: mouse reset did not ACK\n");
|
||||||
@@ -318,8 +312,10 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
|||||||
|
|
||||||
|
|
||||||
uint32_t keyboardId = 0, mouseId = 0;
|
uint32_t keyboardId = 0, mouseId = 0;
|
||||||
KeInputRegisterDevice("ps2-keyboard", 0, &keyboardId);
|
KSTATUS status = KeInputRegisterDevice("ps2-keyboard", 0, &keyboardId);
|
||||||
KeInputRegisterDevice("ps2-mouse", 0, &mouseId);
|
if (!KSUCCESS(status)) return status;
|
||||||
|
status = KeInputRegisterDevice("ps2-mouse", 0, &mouseId);
|
||||||
|
if (!KSUCCESS(status)) return status;
|
||||||
|
|
||||||
KeInitializeDpc(&gKeyboardDpc, Ps2KeyboardDpcRoutine, 0);
|
KeInitializeDpc(&gKeyboardDpc, Ps2KeyboardDpcRoutine, 0);
|
||||||
KeInitializeDpc(&gMouseDpc, Ps2MouseDpcRoutine, 0);
|
KeInitializeDpc(&gMouseDpc, Ps2MouseDpcRoutine, 0);
|
||||||
@@ -332,12 +328,32 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
|||||||
Ps2KeyboardInitialize();
|
Ps2KeyboardInitialize();
|
||||||
Ps2MouseInitialize();
|
Ps2MouseInitialize();
|
||||||
|
|
||||||
KeIrqRegister(PS2_IRQ_KEYBOARD, Ps2KeyboardIsr);
|
KSTATUS irqStatus = KeInterruptConnectIsa(PS2_IRQ_KEYBOARD, 0, 0,
|
||||||
KeIrqRegister(PS2_IRQ_MOUSE, Ps2MouseIsr);
|
Ps2KeyboardIsr, 0, &gKeyboardInterrupt);
|
||||||
Ps2ControllerEnableInterrupts();
|
if (!KSUCCESS(irqStatus)) return irqStatus;
|
||||||
|
irqStatus = KeInterruptConnectIsa(PS2_IRQ_MOUSE, 0, 0,
|
||||||
|
Ps2MouseIsr, 0, &gMouseInterrupt);
|
||||||
|
if (!KSUCCESS(irqStatus)) return irqStatus;
|
||||||
|
|
||||||
DbgPrint("ps2: initialized keyboard=%u mouse=%u\n", keyboardId, mouseId);
|
DbgPrint("ps2: prepared keyboard=%u mouse=%u\n", keyboardId, mouseId);
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTL_DECLARE_MODULE(DriverInitialize);
|
static void Ps2CommitStart(NTL_MODULE* module) {
|
||||||
|
(void)module;
|
||||||
|
Ps2ControllerEnableInterrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Ps2AbortStart(NTL_MODULE* module) {
|
||||||
|
(void)module;
|
||||||
|
if (gMouseInterrupt) {
|
||||||
|
KeInterruptDisconnect(gMouseInterrupt);
|
||||||
|
gMouseInterrupt = (KE_INTERRUPT*)0;
|
||||||
|
}
|
||||||
|
if (gKeyboardInterrupt) {
|
||||||
|
KeInterruptDisconnect(gKeyboardInterrupt);
|
||||||
|
gKeyboardInterrupt = (KE_INTERRUPT*)0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NTL_DECLARE_STAGED_MODULE(DriverInitialize, Ps2CommitStart, Ps2AbortStart);
|
||||||
@@ -2,12 +2,10 @@
|
|||||||
|
|
||||||
#include "ps2.h"
|
#include "ps2.h"
|
||||||
|
|
||||||
// Implements the ps2 Pause operation.
|
|
||||||
void Ps2Pause(void) {
|
void Ps2Pause(void) {
|
||||||
_mm_pause();
|
_mm_pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Wait Input operation.
|
|
||||||
void Ps2WaitInput(void) {
|
void Ps2WaitInput(void) {
|
||||||
int timeout = 100000;
|
int timeout = 100000;
|
||||||
while ((__inbyte(PS2_STAT) & PS2_STAT_IN_FULL) && --timeout) {
|
while ((__inbyte(PS2_STAT) & PS2_STAT_IN_FULL) && --timeout) {
|
||||||
@@ -15,7 +13,6 @@ void Ps2WaitInput(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Wait Output operation.
|
|
||||||
bool Ps2WaitOutput(void) {
|
bool Ps2WaitOutput(void) {
|
||||||
int timeout = 5000000;
|
int timeout = 5000000;
|
||||||
while (!(__inbyte(PS2_STAT) & PS2_STAT_OUT_FULL) && --timeout) {
|
while (!(__inbyte(PS2_STAT) & PS2_STAT_OUT_FULL) && --timeout) {
|
||||||
@@ -24,7 +21,6 @@ bool Ps2WaitOutput(void) {
|
|||||||
return timeout != 0;
|
return timeout != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Flush Output operation.
|
|
||||||
void Ps2FlushOutput(void) {
|
void Ps2FlushOutput(void) {
|
||||||
int timeout = 100000;
|
int timeout = 100000;
|
||||||
while ((__inbyte(PS2_STAT) & PS2_STAT_OUT_FULL) && --timeout) {
|
while ((__inbyte(PS2_STAT) & PS2_STAT_OUT_FULL) && --timeout) {
|
||||||
@@ -32,43 +28,36 @@ void Ps2FlushOutput(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Read Data operation.
|
|
||||||
uint8_t Ps2ReadData(void) {
|
uint8_t Ps2ReadData(void) {
|
||||||
if (!Ps2WaitOutput()) return 0xFFu;
|
if (!Ps2WaitOutput()) return 0xFFu;
|
||||||
return __inbyte(PS2_DATA);
|
return __inbyte(PS2_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Write Command operation.
|
|
||||||
void Ps2WriteCommand(uint8_t command) {
|
void Ps2WriteCommand(uint8_t command) {
|
||||||
Ps2WaitInput();
|
Ps2WaitInput();
|
||||||
__outbyte(PS2_CMD, command);
|
__outbyte(PS2_CMD, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Write Data operation.
|
|
||||||
void Ps2WriteData(uint8_t data) {
|
void Ps2WriteData(uint8_t data) {
|
||||||
Ps2WaitInput();
|
Ps2WaitInput();
|
||||||
__outbyte(PS2_DATA, data);
|
__outbyte(PS2_DATA, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Read Command Byte operation.
|
|
||||||
uint8_t Ps2ReadCommandByte(void) {
|
uint8_t Ps2ReadCommandByte(void) {
|
||||||
Ps2WriteCommand(0x20u);
|
Ps2WriteCommand(0x20u);
|
||||||
return Ps2ReadData();
|
return Ps2ReadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Write Command Byte operation.
|
|
||||||
void Ps2WriteCommandByte(uint8_t commandByte) {
|
void Ps2WriteCommandByte(uint8_t commandByte) {
|
||||||
Ps2WriteCommand(0x60u);
|
Ps2WriteCommand(0x60u);
|
||||||
Ps2WriteData(commandByte);
|
Ps2WriteData(commandByte);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Send Keyboard operation.
|
|
||||||
bool Ps2SendKeyboard(uint8_t byte) {
|
bool Ps2SendKeyboard(uint8_t byte) {
|
||||||
Ps2WriteData(byte);
|
Ps2WriteData(byte);
|
||||||
return Ps2ReadData() == 0xFAu;
|
return Ps2ReadData() == 0xFAu;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ps2 Send Mouse operation.
|
|
||||||
bool Ps2SendMouse(uint8_t byte) {
|
bool Ps2SendMouse(uint8_t byte) {
|
||||||
Ps2WriteCommand(0xD4u);
|
Ps2WriteCommand(0xD4u);
|
||||||
Ps2WriteData(byte);
|
Ps2WriteData(byte);
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
TARGETNAME=ps2
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=DRIVER
|
||||||
|
FLAVOR=DRIVER
|
||||||
|
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib"
|
||||||
|
EXTRA_LFLAGS=/NOENTRY
|
||||||
|
SOURCES=@/code/drivers/input/ps2/ps2.c @/code/drivers/input/ps2/ps2_i8042.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!include $(BASEDIR)\makefile.def
|
||||||
@@ -49,6 +49,7 @@ typedef enum SERIAL_ESCAPE_STATE {
|
|||||||
} SERIAL_ESCAPE_STATE;
|
} SERIAL_ESCAPE_STATE;
|
||||||
|
|
||||||
static KDPC gSerialRxDpc;
|
static KDPC gSerialRxDpc;
|
||||||
|
static KE_INTERRUPT* gSerialInterrupt;
|
||||||
static volatile SERIAL_ESCAPE_STATE gSerialEscapeState;
|
static volatile SERIAL_ESCAPE_STATE gSerialEscapeState;
|
||||||
static volatile uint8_t gSerialCsiNumber;
|
static volatile uint8_t gSerialCsiNumber;
|
||||||
static volatile bool gSerialDropNextLf;
|
static volatile bool gSerialDropNextLf;
|
||||||
@@ -308,7 +309,8 @@ static void SerialQueueRxByte(uint8_t ch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handles receive interrupts for COM1.
|
// Handles receive interrupts for COM1.
|
||||||
static void SerialIsr(void) {
|
static void SerialIsr(void* context) {
|
||||||
|
(void)context;
|
||||||
for (uint32_t i = 0; i < 256u; i++) {
|
for (uint32_t i = 0; i < 256u; i++) {
|
||||||
if ((SerialRead(SERIAL_REG_LSR) & SERIAL_LSR_DATA_READY) == 0)
|
if ((SerialRead(SERIAL_REG_LSR) & SERIAL_LSR_DATA_READY) == 0)
|
||||||
break;
|
break;
|
||||||
@@ -367,11 +369,25 @@ static KSTATUS SerialInitialize(NTL_MODULE* module) {
|
|||||||
gSerialRxTail = 0;
|
gSerialRxTail = 0;
|
||||||
gSerialRxDropped = 0;
|
gSerialRxDropped = 0;
|
||||||
|
|
||||||
KeIrqRegister(SERIAL_COM1_IRQ, SerialIsr);
|
KSTATUS irqStatus = KeInterruptConnectIsa(SERIAL_COM1_IRQ, 0, 0,
|
||||||
SerialWrite(SERIAL_REG_IER, SERIAL_IER_RX_READY);
|
SerialIsr, 0, &gSerialInterrupt);
|
||||||
|
if (!KSUCCESS(irqStatus)) return irqStatus;
|
||||||
|
|
||||||
DbgPrint("serial: initialized COM1 input device=%u irq=%u\n", deviceId, SERIAL_COM1_IRQ);
|
DbgPrint("serial: prepared COM1 input device=%u irq=%u\n", deviceId, SERIAL_COM1_IRQ);
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTL_DECLARE_MODULE(SerialInitialize);
|
static void SerialCommitStart(NTL_MODULE* module) {
|
||||||
|
(void)module;
|
||||||
|
SerialWrite(SERIAL_REG_IER, SERIAL_IER_RX_READY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SerialAbortStart(NTL_MODULE* module) {
|
||||||
|
(void)module;
|
||||||
|
if (!gSerialInterrupt) return;
|
||||||
|
SerialWrite(SERIAL_REG_IER, 0);
|
||||||
|
KeInterruptDisconnect(gSerialInterrupt);
|
||||||
|
gSerialInterrupt = (KE_INTERRUPT*)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTL_DECLARE_STAGED_MODULE(SerialInitialize, SerialCommitStart, SerialAbortStart);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
TARGETNAME=serial
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=DRIVER
|
||||||
|
FLAVOR=DRIVER
|
||||||
|
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib"
|
||||||
|
EXTRA_LFLAGS=/NOENTRY
|
||||||
|
SOURCES=@/code/drivers/input/serial/serial.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DIRS=lwip rtl8139 rtl816x
|
||||||
@@ -146,7 +146,6 @@ static NET_STACK_PROVIDER gLwipProvider = {
|
|||||||
LwipProviderReceiveFrame,
|
LwipProviderReceiveFrame,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements the err To Status operation.
|
|
||||||
static KSTATUS LwipErrToStatus(err_t err) {
|
static KSTATUS LwipErrToStatus(err_t err) {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case ERR_OK: return NTLSTATUS_SUCCESS;
|
case ERR_OK: return NTLSTATUS_SUCCESS;
|
||||||
@@ -167,7 +166,6 @@ static KSTATUS LwipErrToStatus(err_t err) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the ascii Is Digit operation.
|
|
||||||
static bool LwipAsciiIsDigit(char c) {
|
static bool LwipAsciiIsDigit(char c) {
|
||||||
return c >= '0' && c <= '9';
|
return c >= '0' && c <= '9';
|
||||||
}
|
}
|
||||||
@@ -365,20 +363,17 @@ static KSTATUS LwipLoadNetifConfig(const NET_DEVICE* device, LWIP_NETIF_CONFIG*
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the socket Lock operation.
|
|
||||||
static KSTATUS LwipSocketLock(LWIP_PROVIDER_SOCKET* s) {
|
static KSTATUS LwipSocketLock(LWIP_PROVIDER_SOCKET* s) {
|
||||||
if (!s || !s->Lock)
|
if (!s || !s->Lock)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
return KeWaitSemaphore(s->Lock, KE_WAIT_INFINITE);
|
return KeWaitSemaphore(s->Lock, KE_WAIT_INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the socket Unlock operation.
|
|
||||||
static void LwipSocketUnlock(LWIP_PROVIDER_SOCKET* s) {
|
static void LwipSocketUnlock(LWIP_PROVIDER_SOCKET* s) {
|
||||||
if (s && s->Lock)
|
if (s && s->Lock)
|
||||||
KeSignalSemaphore(s->Lock);
|
KeSignalSemaphore(s->Lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the socket Callback operation.
|
|
||||||
static void LwipSocketCallback(struct netconn* conn, enum netconn_evt evt, u16_t len) {
|
static void LwipSocketCallback(struct netconn* conn, enum netconn_evt evt, u16_t len) {
|
||||||
(void)len;
|
(void)len;
|
||||||
if (!conn)
|
if (!conn)
|
||||||
@@ -571,7 +566,6 @@ static bool LwipSocketFamilyMatches(const LWIP_PROVIDER_SOCKET* s, const SYS_SOC
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the socket Make Ip operation.
|
|
||||||
static KSTATUS LwipSocketMakeIp(const SYS_SOCKET_ADDRESS_K* address, ip_addr_t* out) {
|
static KSTATUS LwipSocketMakeIp(const SYS_SOCKET_ADDRESS_K* address, ip_addr_t* out) {
|
||||||
if (!address || !out)
|
if (!address || !out)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -595,7 +589,6 @@ static KSTATUS LwipSocketMakeIp(const SYS_SOCKET_ADDRESS_K* address, ip_addr_t*
|
|||||||
return NTLSTATUS_NOT_SUPPORTED;
|
return NTLSTATUS_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the socket Fill Address operation.
|
|
||||||
static void LwipSocketFillAddress(SYS_SOCKET_ADDRESS_K* out, const ip_addr_t* ip, u16_t port) {
|
static void LwipSocketFillAddress(SYS_SOCKET_ADDRESS_K* out, const ip_addr_t* ip, u16_t port) {
|
||||||
if (!out)
|
if (!out)
|
||||||
return;
|
return;
|
||||||
@@ -624,7 +617,6 @@ static void LwipSocketFillAddress(SYS_SOCKET_ADDRESS_K* out, const ip_addr_t* ip
|
|||||||
out->Address[3] = (uint8_t)ip4_addr4(ip_2_ip4(ip));
|
out->Address[3] = (uint8_t)ip4_addr4(ip_2_ip4(ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the low Level Output operation.
|
|
||||||
static err_t LwipLowLevelOutput(struct netif* netif, struct pbuf* p) {
|
static err_t LwipLowLevelOutput(struct netif* netif, struct pbuf* p) {
|
||||||
LWIP_BINDING* b = (LWIP_BINDING*)netif->state;
|
LWIP_BINDING* b = (LWIP_BINDING*)netif->state;
|
||||||
if (!b || !b->Device || !p || p->tot_len < NET_ETHERNET_HEADER_LENGTH)
|
if (!b || !b->Device || !p || p->tot_len < NET_ETHERNET_HEADER_LENGTH)
|
||||||
@@ -652,7 +644,6 @@ static err_t LwipLowLevelOutput(struct netif* netif, struct pbuf* p) {
|
|||||||
return KSUCCESS(st) ? ERR_OK : ERR_IF;
|
return KSUCCESS(st) ? ERR_OK : ERR_IF;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the netif Init operation.
|
|
||||||
static err_t LwipNetifInit(struct netif* netif) {
|
static err_t LwipNetifInit(struct netif* netif) {
|
||||||
LWIP_BINDING* b = (LWIP_BINDING*)netif->state;
|
LWIP_BINDING* b = (LWIP_BINDING*)netif->state;
|
||||||
if (!b || !b->Device)
|
if (!b || !b->Device)
|
||||||
@@ -773,7 +764,6 @@ static KSTATUS LwipDelayThread(uint64_t milliseconds) {
|
|||||||
return KeDelayThread(milliseconds);
|
return KeDelayThread(milliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the stack Initialize operation.
|
|
||||||
static KSTATUS LwipStackInitialize(void) {
|
static KSTATUS LwipStackInitialize(void) {
|
||||||
if (gLwipInitialized)
|
if (gLwipInitialized)
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
@@ -796,7 +786,6 @@ static KSTATUS LwipStackInitialize(void) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Attach Device operation.
|
|
||||||
static KSTATUS LwipProviderAttachDevice(NET_DEVICE* device) {
|
static KSTATUS LwipProviderAttachDevice(NET_DEVICE* device) {
|
||||||
if (!gLwipInitialized)
|
if (!gLwipInitialized)
|
||||||
return NTLSTATUS_NOT_SUPPORTED;
|
return NTLSTATUS_NOT_SUPPORTED;
|
||||||
@@ -855,7 +844,6 @@ static KSTATUS LwipProviderAttachDevice(NET_DEVICE* device) {
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Receive Frame operation.
|
|
||||||
static KSTATUS LwipProviderReceiveFrame(NET_DEVICE* device, const void* frame, size_t length) {
|
static KSTATUS LwipProviderReceiveFrame(NET_DEVICE* device, const void* frame, size_t length) {
|
||||||
if (!gLwipInitialized)
|
if (!gLwipInitialized)
|
||||||
return NTLSTATUS_NOT_SUPPORTED;
|
return NTLSTATUS_NOT_SUPPORTED;
|
||||||
@@ -889,7 +877,6 @@ static KSTATUS LwipProviderReceiveFrame(NET_DEVICE* device, const void* frame, s
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Socket Create operation.
|
|
||||||
static KSTATUS LwipProviderSocketCreate(uint32_t domain, uint32_t type, uint32_t protocol, void** outSocket) {
|
static KSTATUS LwipProviderSocketCreate(uint32_t domain, uint32_t type, uint32_t protocol, void** outSocket) {
|
||||||
if (!outSocket)
|
if (!outSocket)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -937,7 +924,6 @@ static KSTATUS LwipProviderSocketCreate(uint32_t domain, uint32_t type, uint32_t
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Socket Close operation.
|
|
||||||
static void LwipProviderSocketClose(void* socket) {
|
static void LwipProviderSocketClose(void* socket) {
|
||||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||||
if (!s)
|
if (!s)
|
||||||
@@ -964,7 +950,6 @@ static void LwipProviderSocketClose(void* socket) {
|
|||||||
MmFreePool(s);
|
MmFreePool(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Bind operation.
|
|
||||||
static KSTATUS LwipProviderBind(void* socket, const SYS_SOCKET_ADDRESS_K* address, size_t addressSize) {
|
static KSTATUS LwipProviderBind(void* socket, const SYS_SOCKET_ADDRESS_K* address, size_t addressSize) {
|
||||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||||
if (!s || !address)
|
if (!s || !address)
|
||||||
@@ -999,7 +984,6 @@ static KSTATUS LwipProviderBind(void* socket, const SYS_SOCKET_ADDRESS_K* addres
|
|||||||
return LwipErrToStatus(err);
|
return LwipErrToStatus(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Listen operation.
|
|
||||||
static KSTATUS LwipProviderListen(void* socket, uint32_t backlog) {
|
static KSTATUS LwipProviderListen(void* socket, uint32_t backlog) {
|
||||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||||
if (!s)
|
if (!s)
|
||||||
@@ -1028,7 +1012,6 @@ static KSTATUS LwipProviderListen(void* socket, uint32_t backlog) {
|
|||||||
return LwipErrToStatus(err);
|
return LwipErrToStatus(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Accept operation.
|
|
||||||
static KSTATUS LwipProviderAccept(void* socket, void** acceptedOut, SYS_SOCKET_ADDRESS_K* remoteOut, volatile uint8_t* cancelRequested) {
|
static KSTATUS LwipProviderAccept(void* socket, void** acceptedOut, SYS_SOCKET_ADDRESS_K* remoteOut, volatile uint8_t* cancelRequested) {
|
||||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||||
if (!s || !acceptedOut)
|
if (!s || !acceptedOut)
|
||||||
@@ -1087,7 +1070,6 @@ static KSTATUS LwipProviderAccept(void* socket, void** acceptedOut, SYS_SOCKET_A
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Connect operation.
|
|
||||||
static KSTATUS LwipProviderConnect(void* socket, const SYS_SOCKET_ADDRESS_K* address, size_t addressSize, volatile uint8_t* cancelRequested) {
|
static KSTATUS LwipProviderConnect(void* socket, const SYS_SOCKET_ADDRESS_K* address, size_t addressSize, volatile uint8_t* cancelRequested) {
|
||||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||||
if (!s || !address)
|
if (!s || !address)
|
||||||
@@ -1173,7 +1155,6 @@ static KSTATUS LwipProviderConnect(void* socket, const SYS_SOCKET_ADDRESS_K* add
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Send operation.
|
|
||||||
static KSTATUS LwipProviderSend(void* socket, const void* buffer, size_t length, uint32_t flags, size_t* sentOut) {
|
static KSTATUS LwipProviderSend(void* socket, const void* buffer, size_t length, uint32_t flags, size_t* sentOut) {
|
||||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||||
if (sentOut)
|
if (sentOut)
|
||||||
@@ -1257,7 +1238,6 @@ static KSTATUS LwipReceiveFromBuffered(LWIP_PROVIDER_SOCKET* s, uint8_t* out,
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Receive operation.
|
|
||||||
static KSTATUS LwipProviderReceive(void* socket, void* buffer, size_t length, uint32_t flags, size_t* receivedOut, volatile uint8_t* cancelRequested) {
|
static KSTATUS LwipProviderReceive(void* socket, void* buffer, size_t length, uint32_t flags, size_t* receivedOut, volatile uint8_t* cancelRequested) {
|
||||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||||
if (receivedOut)
|
if (receivedOut)
|
||||||
@@ -1462,7 +1442,6 @@ static KSTATUS LwipProviderReceiveFrom(void* socket, void* buffer, size_t length
|
|||||||
return LwipErrToStatus(err);
|
return LwipErrToStatus(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Set Option operation.
|
|
||||||
static KSTATUS LwipProviderSetOption(void* socket, uint32_t option, const void* value, size_t valueSize) {
|
static KSTATUS LwipProviderSetOption(void* socket, uint32_t option, const void* value, size_t valueSize) {
|
||||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||||
if (!s || !value)
|
if (!s || !value)
|
||||||
@@ -1501,7 +1480,6 @@ static KSTATUS LwipProviderSetOption(void* socket, uint32_t option, const void*
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Get Option operation.
|
|
||||||
static KSTATUS LwipProviderGetOption(void* socket, uint32_t option, void* value, size_t valueSize, size_t* actualSizeOut) {
|
static KSTATUS LwipProviderGetOption(void* socket, uint32_t option, void* value, size_t valueSize, size_t* actualSizeOut) {
|
||||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||||
if (actualSizeOut)
|
if (actualSizeOut)
|
||||||
@@ -1538,7 +1516,6 @@ static KSTATUS LwipProviderGetOption(void* socket, uint32_t option, void* value,
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Poll operation.
|
|
||||||
static KSTATUS LwipProviderPoll(void* socket, uint32_t events, uint32_t* returnedEventsOut) {
|
static KSTATUS LwipProviderPoll(void* socket, uint32_t events, uint32_t* returnedEventsOut) {
|
||||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||||
if (!s || !returnedEventsOut)
|
if (!s || !returnedEventsOut)
|
||||||
@@ -1577,7 +1554,6 @@ static KSTATUS LwipProviderPoll(void* socket, uint32_t events, uint32_t* returne
|
|||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Shutdown operation.
|
|
||||||
static KSTATUS LwipProviderShutdown(void* socket, uint32_t how) {
|
static KSTATUS LwipProviderShutdown(void* socket, uint32_t how) {
|
||||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||||
if (!s)
|
if (!s)
|
||||||
@@ -1648,7 +1624,6 @@ static void LwipResolveStartCallback(void* argument) {
|
|||||||
LwipResolveRelease(context);
|
LwipResolveRelease(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the provider Resolve Host operation.
|
|
||||||
static KSTATUS LwipProviderResolveHost(const char* name, uint32_t family, SYS_SOCKET_ADDRESS_K* addressOut) {
|
static KSTATUS LwipProviderResolveHost(const char* name, uint32_t family, SYS_SOCKET_ADDRESS_K* addressOut) {
|
||||||
if (!name || !addressOut)
|
if (!name || !addressOut)
|
||||||
return NTLSTATUS_INVALID_PARAMETER;
|
return NTLSTATUS_INVALID_PARAMETER;
|
||||||
@@ -1819,7 +1794,6 @@ static KSTATUS LwipDispatchInternalDeviceControl(DEVICE_OBJECT* device, IRP* irp
|
|||||||
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
||||||
(void)module;
|
(void)module;
|
||||||
|
|
||||||
DbgPrint("lwIP: driver loading...\n");
|
|
||||||
|
|
||||||
LWIP_NETIF_CONFIG defaultConfig;
|
LWIP_NETIF_CONFIG defaultConfig;
|
||||||
KSTATUS st = LwipLoadConfigFromSection(LWIP_SETTINGS_DEFAULT_SECTION, &defaultConfig);
|
KSTATUS st = LwipLoadConfigFromSection(LWIP_SETTINGS_DEFAULT_SECTION, &defaultConfig);
|
||||||
@@ -1852,7 +1826,6 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
|||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgPrint("lwIP: driver initialized\n");
|
|
||||||
return NTLSTATUS_SUCCESS;
|
return NTLSTATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ struct sys_mbox {
|
|||||||
static uint64_t (*gLwipQueryTicksUs)(void) = 0;
|
static uint64_t (*gLwipQueryTicksUs)(void) = 0;
|
||||||
static uint32_t gRandState = 0x4b4e4554u; // 'KNET'
|
static uint32_t gRandState = 0x4b4e4554u; // 'KNET'
|
||||||
|
|
||||||
// Implements the port Set Timer Query operation.
|
|
||||||
void LwipPortSetTimerQuery(uint64_t (*query_ticks_us)(void)) {
|
void LwipPortSetTimerQuery(uint64_t (*query_ticks_us)(void)) {
|
||||||
gLwipQueryTicksUs = query_ticks_us;
|
gLwipQueryTicksUs = query_ticks_us;
|
||||||
}
|
}
|
||||||
@@ -54,7 +53,6 @@ unsigned int lwip_port_rand(void) {
|
|||||||
return gRandState;
|
return gRandState;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the sys init operation.
|
|
||||||
void sys_init(void) {
|
void sys_init(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +79,6 @@ u32_t sys_jiffies(void) {
|
|||||||
#undef errno
|
#undef errno
|
||||||
#endif
|
#endif
|
||||||
int errno;
|
int errno;
|
||||||
// Implements the errno operation.
|
|
||||||
int* __cdecl _errno(void) { return &errno; }
|
int* __cdecl _errno(void) { return &errno; }
|
||||||
|
|
||||||
err_t sys_sem_new(sys_sem_t* sem, u8_t count) {
|
err_t sys_sem_new(sys_sem_t* sem, u8_t count) {
|
||||||
@@ -104,7 +101,6 @@ err_t sys_sem_new(sys_sem_t* sem, u8_t count) {
|
|||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the sys sem signal operation.
|
|
||||||
void sys_sem_signal(sys_sem_t* sem) {
|
void sys_sem_signal(sys_sem_t* sem) {
|
||||||
if (sem && *sem && (*sem)->Sem)
|
if (sem && *sem && (*sem)->Sem)
|
||||||
KeSignalSemaphore((*sem)->Sem);
|
KeSignalSemaphore((*sem)->Sem);
|
||||||
@@ -127,7 +123,6 @@ u32_t sys_arch_sem_wait(sys_sem_t* sem, u32_t timeout) {
|
|||||||
: SYS_ARCH_TIMEOUT;
|
: SYS_ARCH_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the sys sem free operation.
|
|
||||||
void sys_sem_free(sys_sem_t* sem) {
|
void sys_sem_free(sys_sem_t* sem) {
|
||||||
if (!sem || !*sem)
|
if (!sem || !*sem)
|
||||||
return;
|
return;
|
||||||
@@ -157,19 +152,16 @@ err_t sys_mutex_new(sys_mutex_t* mutex) {
|
|||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the sys mutex lock operation.
|
|
||||||
void sys_mutex_lock(sys_mutex_t* mutex) {
|
void sys_mutex_lock(sys_mutex_t* mutex) {
|
||||||
if (mutex && *mutex && (*mutex)->Sem)
|
if (mutex && *mutex && (*mutex)->Sem)
|
||||||
(void)KeWaitSemaphore((*mutex)->Sem, KE_WAIT_INFINITE);
|
(void)KeWaitSemaphore((*mutex)->Sem, KE_WAIT_INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the sys mutex unlock operation.
|
|
||||||
void sys_mutex_unlock(sys_mutex_t* mutex) {
|
void sys_mutex_unlock(sys_mutex_t* mutex) {
|
||||||
if (mutex && *mutex && (*mutex)->Sem)
|
if (mutex && *mutex && (*mutex)->Sem)
|
||||||
KeSignalSemaphore((*mutex)->Sem);
|
KeSignalSemaphore((*mutex)->Sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the sys mutex free operation.
|
|
||||||
void sys_mutex_free(sys_mutex_t* mutex) {
|
void sys_mutex_free(sys_mutex_t* mutex) {
|
||||||
if (!mutex || !*mutex)
|
if (!mutex || !*mutex)
|
||||||
return;
|
return;
|
||||||
@@ -179,7 +171,6 @@ void sys_mutex_free(sys_mutex_t* mutex) {
|
|||||||
*mutex = 0;
|
*mutex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the mbox Try Post operation.
|
|
||||||
static err_t LwipMboxTryPost(sys_mbox_t* mbox, void* msg) {
|
static err_t LwipMboxTryPost(sys_mbox_t* mbox, void* msg) {
|
||||||
if (!mbox || !*mbox || !(*mbox)->Valid)
|
if (!mbox || !*mbox || !(*mbox)->Valid)
|
||||||
return ERR_ARG;
|
return ERR_ARG;
|
||||||
@@ -232,7 +223,6 @@ err_t sys_mbox_new(sys_mbox_t* mbox, int size) {
|
|||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the sys mbox post operation.
|
|
||||||
void sys_mbox_post(sys_mbox_t* mbox, void* msg) {
|
void sys_mbox_post(sys_mbox_t* mbox, void* msg) {
|
||||||
// lwIP promises this is not called from ISR context.
|
// lwIP promises this is not called from ISR context.
|
||||||
while (LwipMboxTryPost(mbox, msg) != ERR_OK)
|
while (LwipMboxTryPost(mbox, msg) != ERR_OK)
|
||||||
@@ -247,7 +237,6 @@ err_t sys_mbox_trypost_fromisr(sys_mbox_t* mbox, void* msg) {
|
|||||||
return LwipMboxTryPost(mbox, msg);
|
return LwipMboxTryPost(mbox, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the mbox Pop After Item operation.
|
|
||||||
static u32_t LwipMboxPopAfterItem(sys_mbox_t* mbox, void** msg, u32_t waited) {
|
static u32_t LwipMboxPopAfterItem(sys_mbox_t* mbox, void** msg, u32_t waited) {
|
||||||
struct sys_mbox* m = *mbox;
|
struct sys_mbox* m = *mbox;
|
||||||
uintptr_t flags = KeAcquireSpinlock(&m->Lock);
|
uintptr_t flags = KeAcquireSpinlock(&m->Lock);
|
||||||
@@ -296,7 +285,6 @@ u32_t sys_arch_mbox_tryfetch(sys_mbox_t* mbox, void** msg) {
|
|||||||
return LwipMboxPopAfterItem(mbox, msg, 0);
|
return LwipMboxPopAfterItem(mbox, msg, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the sys mbox free operation.
|
|
||||||
void sys_mbox_free(sys_mbox_t* mbox) {
|
void sys_mbox_free(sys_mbox_t* mbox) {
|
||||||
if (!mbox || !*mbox)
|
if (!mbox || !*mbox)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
!include $(BASEDIR)\makefile.def
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
TARGETNAME=lwip
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=DRIVER
|
||||||
|
FLAVOR=LWIP
|
||||||
|
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib"
|
||||||
|
EXTRA_LFLAGS=/NOENTRY
|
||||||
|
INCLUDES=$(BASEDIR)\code\drivers\net\lwip\include;$(BASEDIR)\code\drivers\net\lwip\third_party\lwip\src\include
|
||||||
|
SOURCES=@/code/drivers/net/lwip/lwip_sys_arch.c @/code/drivers/net/lwip/lwip_stack.c @/code/drivers/net/lwip/third_party/lwip/src/core/init.c @/code/drivers/net/lwip/third_party/lwip/src/core/def.c @/code/drivers/net/lwip/third_party/lwip/src/core/dns.c @/code/drivers/net/lwip/third_party/lwip/src/core/inet_chksum.c \
|
||||||
|
@/code/drivers/net/lwip/third_party/lwip/src/core/ip.c @/code/drivers/net/lwip/third_party/lwip/src/core/mem.c @/code/drivers/net/lwip/third_party/lwip/src/core/memp.c @/code/drivers/net/lwip/third_party/lwip/src/core/netif.c @/code/drivers/net/lwip/third_party/lwip/src/core/pbuf.c @/code/drivers/net/lwip/third_party/lwip/src/core/raw.c \
|
||||||
|
@/code/drivers/net/lwip/third_party/lwip/src/core/stats.c @/code/drivers/net/lwip/third_part | ||||||