├── .gitignore ├── LICENSE ├── README.md ├── buses └── gpio │ ├── qcgpio.c │ ├── qcgpio.inx │ ├── qcgpio.rc │ ├── qcgpio.vcxproj │ └── qcgpio.vcxproj.Filters └── hals └── halext ├── HalExtQcHypGic3IrmSupport.sln └── HalExtQcHypGic3IrmSupport ├── HalExtQcHypGic3IrmSupport.c ├── HalExtQcHypGic3IrmSupport.def ├── HalExtQcHypGic3IrmSupport.inx ├── HalExtQcHypGic3IrmSupport.rc ├── HalExtQcHypGic3IrmSupport.vcxproj └── HalExtQcHypGic3IrmSupport.vcxproj.Filters /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.tlog 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 298 | *.vbp 299 | 300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 301 | *.dsw 302 | *.dsp 303 | 304 | # Visual Studio 6 technical files 305 | *.ncb 306 | *.aps 307 | 308 | # Visual Studio LightSwitch build output 309 | **/*.HTMLClient/GeneratedArtifacts 310 | **/*.DesktopClient/GeneratedArtifacts 311 | **/*.DesktopClient/ModelManifest.xml 312 | **/*.Server/GeneratedArtifacts 313 | **/*.Server/ModelManifest.xml 314 | _Pvt_Extensions 315 | 316 | # Paket dependency manager 317 | .paket/paket.exe 318 | paket-files/ 319 | 320 | # FAKE - F# Make 321 | .fake/ 322 | 323 | # CodeRush personal settings 324 | .cr/personal 325 | 326 | # Python Tools for Visual Studio (PTVS) 327 | __pycache__/ 328 | *.pyc 329 | 330 | # Cake - Uncomment if you are using it 331 | # tools/** 332 | # !tools/packages.config 333 | 334 | # Tabs Studio 335 | *.tss 336 | 337 | # Telerik's JustMock configuration file 338 | *.jmconfig 339 | 340 | # BizTalk build output 341 | *.btp.cs 342 | *.btm.cs 343 | *.odx.cs 344 | *.xsd.cs 345 | 346 | # OpenCover UI analysis results 347 | OpenCover/ 348 | 349 | # Azure Stream Analytics local run output 350 | ASALocalRun/ 351 | 352 | # MSBuild Binary and Structured Log 353 | *.binlog 354 | 355 | # NVidia Nsight GPU debugger configuration file 356 | *.nvuser 357 | 358 | # MFractors (Xamarin productivity tool) working folder 359 | .mfractor/ 360 | 361 | # Local History for Visual Studio 362 | .localhistory/ 363 | 364 | # Visual Studio History (VSHistory) files 365 | .vshistory/ 366 | 367 | # BeatPulse healthcheck temp database 368 | healthchecksdb 369 | 370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 371 | MigrationBackup/ 372 | 373 | # Ionide (cross platform F# VS Code tools) working folder 374 | .ionide/ 375 | 376 | # Fody - auto-generated XML schema 377 | FodyWeavers.xsd 378 | 379 | # VS Code files for those working on multiple tools 380 | .vscode/* 381 | !.vscode/settings.json 382 | !.vscode/tasks.json 383 | !.vscode/launch.json 384 | !.vscode/extensions.json 385 | *.code-workspace 386 | 387 | # Local History for Visual Studio Code 388 | .history/ 389 | 390 | # Windows Installer files from build outputs 391 | *.cab 392 | *.msi 393 | *.msix 394 | *.msm 395 | *.msp 396 | 397 | # JetBrains Rider 398 | *.sln.iml 399 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 WOA Project 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Project-Croissant 2 | Project Croissant aims to provide open source Windows Drivers for various Qualcomm Snapdragon Platforms as well as compatibility bridges for existing drivers whenever possible. 3 | -------------------------------------------------------------------------------- /buses/gpio/qcgpio.c: -------------------------------------------------------------------------------- 1 | 2 | /*++ 3 | 4 | Copyright (c) Microsoft Corporation. All rights reserved. 5 | 6 | THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 7 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 8 | IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR 9 | PURPOSE. 10 | 11 | Module Name: 12 | 13 | qcgpio.c 14 | 15 | Abstract: 16 | 17 | This sample implements a GPIO client driver for simulated GPIO (QcGpio) 18 | controller. 19 | 20 | Note: DIRQL in the comments below refers to device IRQL, which is any 21 | IRQL > DISPATCH_LEVEL (and less than some IRQL reserved for OS use). 22 | 23 | 24 | Environment: 25 | 26 | Kernel mode 27 | 28 | --*/ 29 | 30 | 31 | // 32 | // The QcGpio controller has 4 GPIO banks, with banks consisting of 33 | // 32 pins each. Any pin can be configured for interrupt, input or output. 34 | // Each bank has the the following registers. The register set for different 35 | // banks are laid out adjacent to one another in the physical memory map. 36 | // 37 | // Register | Offset | Size 38 | // ------------------------------------------------ 39 | // ModeRegister | 0x0 | 4 bytes 40 | // PolarityRegister | 0x4 | 8 bytes 41 | // EnableRegister | 0xC | 4 bytes 42 | // StatusRegister | 0x10 | 4 bytes 43 | // DirectionRegister | 0x14 | 4 bytes 44 | // LevelRegister | 0x18 | 4 bytes 45 | // 46 | // Mode Register - Interrupt mode (Level = 0x1 or Edge = 0x0) for pins 47 | // enabled for interrupts. 48 | // 49 | // Polarity Register - ActiveLow (0x0) or ActiveHigh (0x1) for Level-triggered 50 | // interrupts; Falling-edge (0x0), Rising-edge (0x1), or Both-Edges (0x3) 51 | // for Edge-triggered interrupts. Note there are two bits per pin. 52 | // 53 | // Enable Register - A mask of which pins are enabled for interrupt. A bit 54 | // is set if the pin is enabled for interrupt. 55 | // 56 | // Status Register - A register containing which pins are actively interrupting. 57 | // If any of the bit is set, then the GPIO controller's interrupt fires. 58 | // 59 | // Direction Register - A register which indicates whether a given pin is 60 | // configured for input (0x1) or output (0x0). 61 | // 62 | // LevelRegister - A bitmask which indicates holds the value for a given pin 63 | // (i.e. whether the pin is high (0x1) or low (0x0)). 64 | // 65 | 66 | 67 | // 68 | // ------------------------------------------------------------------- Includes 69 | // 70 | 71 | #include 72 | #include 73 | #include 74 | 75 | // 76 | // -------------------------------------------------------------------- Defines 77 | // 78 | 79 | // 80 | // Define total number of pins on the simulated GPIO controller. 81 | // 82 | 83 | #define SIM_GPIO_TOTAL_PINS (4 * 32) 84 | #define SIM_GPIO_PINS_PER_BANK (32) 85 | #define SIM_GPIO_TOTAL_BANKS (4) 86 | 87 | // 88 | // Pool tag for QcGpio allocations. 89 | // 90 | 91 | #define SIM_GPIO_POOL_TAG 'GmiS' 92 | 93 | // 94 | // Define that controls whether f-state based power management will be supported 95 | // or not by the client driver. 96 | // 97 | 98 | #define ENABLE_F_STATE_POWER_MGMT 99 | 100 | // 101 | // Define F1 state residency (in sec), latency values (in sec) and nominal 102 | // power. 103 | // 104 | // This sample demonstrates F-state management effected as part of a critical 105 | // system transition (when the system enters connected-standby). To prevent a 106 | // GPIO bank from being transitioned into a low power state as part of runtime 107 | // idle power management (by mini-PEP), specify very high values for residency 108 | // and transition latency. 109 | // 110 | // If GPIO banks need to be runtime power managed, then specify more reasonable 111 | // values below. 112 | // 113 | 114 | #ifdef ENABLE_F_STATE_POWER_MGMT 115 | 116 | #define SIM_GPIO_F1_NOMINAL_POWER (0) 117 | #define SIM_GPIO_F1_RESIDENCY (8*60*60) // 8hrs 118 | #define SIM_GPIO_F1_TRANSITION (1*60*60) // 1hr 119 | 120 | #endif 121 | 122 | // 123 | // Macro for pointer arithmetic. 124 | // 125 | 126 | #define Add2Ptr(Ptr, Value) ((PVOID)((PUCHAR)(Ptr) + (Value))) 127 | 128 | // 129 | // Determine whether the given pin is reserved or not. Currently no pins are 130 | // reserved on the simulated GPIO controller. 131 | // 132 | 133 | __pragma(warning(disable: 4127)) // conditional expression is a constant 134 | 135 | // 136 | // ---------------------------------------------------------------------- Types 137 | // 138 | 139 | // 140 | // Define the registers within the QcGPIO controller. There are 32 pins per 141 | // controller. Note this is a logical device and thus may correspond to a 142 | // physical bank or module if the GPIO controller in hardware has more than 143 | // 32 pins. 144 | // 145 | 146 | 147 | 148 | typedef struct _SIM_GPIO_REGISTERS { 149 | ULONG ModeRegister; 150 | ULONG PolarityRegister[2]; 151 | ULONG EnableRegister; 152 | ULONG StatusRegister; 153 | ULONG DirectionRegister; 154 | ULONG LevelRegister; 155 | } SIM_GPIO_REGISTERS, *PSIM_GPIO_REGISTERS; 156 | 157 | typedef struct _SIM_GPIO_BANK { 158 | LARGE_INTEGER PhysicalBaseAddress; 159 | PSIM_GPIO_REGISTERS Registers; 160 | ULONG Length; 161 | SIM_GPIO_REGISTERS SavedContext; 162 | } SIM_GPIO_BANK, *PSIM_GPIO_BANK; 163 | 164 | // 165 | // The QcGPIO client driver device extension. 166 | // 167 | 168 | typedef struct _SIM_GPIO_CONTEXT { 169 | USHORT TotalPins; 170 | LARGE_INTEGER PhysicalBaseAddress; 171 | PSIM_GPIO_REGISTERS ControllerBase; 172 | ULONG Length; 173 | SIM_GPIO_BANK Banks[SIM_GPIO_TOTAL_BANKS]; 174 | } SIM_GPIO_CONTEXT, *PSIM_GPIO_CONTEXT; 175 | 176 | SIM_GPIO_REGISTERS GlobalGpioRegisters[SIM_GPIO_TOTAL_BANKS] = {0}; 177 | 178 | // 179 | // ----------------------------------------------------------------- Prototypes 180 | // 181 | 182 | DRIVER_INITIALIZE DriverEntry; 183 | 184 | EVT_WDF_DRIVER_UNLOAD QcGpioEvtDriverUnload; 185 | EVT_WDF_DRIVER_DEVICE_ADD QcGpioEvtDeviceAdd; 186 | 187 | // 188 | // General interfaces. 189 | // 190 | 191 | GPIO_CLIENT_PREPARE_CONTROLLER QcGpioPrepareController; 192 | GPIO_CLIENT_RELEASE_CONTROLLER QcGpioReleaseController; 193 | GPIO_CLIENT_QUERY_CONTROLLER_BASIC_INFORMATION 194 | QcGpioQueryControllerBasicInformation; 195 | 196 | GPIO_CLIENT_QUERY_SET_CONTROLLER_INFORMATION 197 | QcGpioQuerySetControllerInformation; 198 | 199 | GPIO_CLIENT_START_CONTROLLER QcGpioStartController; 200 | GPIO_CLIENT_STOP_CONTROLLER QcGpioStopController; 201 | 202 | // 203 | // Interrupt enable, disable, mask and unmask handlers. 204 | // 205 | 206 | GPIO_CLIENT_ENABLE_INTERRUPT QcGpioEnableInterrupt; 207 | GPIO_CLIENT_DISABLE_INTERRUPT QcGpioDisableInterrupt; 208 | GPIO_CLIENT_MASK_INTERRUPTS QcGpioMaskInterrupts; 209 | GPIO_CLIENT_UNMASK_INTERRUPT QcGpioUnmaskInterrupt; 210 | GPIO_CLIENT_RECONFIGURE_INTERRUPT QcGpioReconfigureInterrupt; 211 | 212 | // 213 | // Handlers to query active/enabled interrupts and clear active interrupts. 214 | // 215 | 216 | GPIO_CLIENT_QUERY_ACTIVE_INTERRUPTS QcGpioQueryActiveInterrupts; 217 | GPIO_CLIENT_CLEAR_ACTIVE_INTERRUPTS QcGpioClearActiveInterrupts; 218 | GPIO_CLIENT_QUERY_ENABLED_INTERRUPTS QcGpioQueryEnabledInterrupts; 219 | 220 | // 221 | // Handlers for GPIO I/O operations. 222 | // 223 | 224 | GPIO_CLIENT_CONNECT_IO_PINS QcGpioConnectIoPins; 225 | GPIO_CLIENT_DISCONNECT_IO_PINS QcGpioDisconnectIoPins; 226 | GPIO_CLIENT_READ_PINS_MASK QcGpioReadGpioPins; 227 | GPIO_CLIENT_WRITE_PINS_MASK QcGpioWriteGpioPins; 228 | 229 | // 230 | // Handlers for save and restore hardware context callbacks. 231 | // 232 | 233 | GPIO_CLIENT_SAVE_BANK_HARDWARE_CONTEXT QcGpioSaveBankHardwareContext; 234 | GPIO_CLIENT_RESTORE_BANK_HARDWARE_CONTEXT QcGpioRestoreBankHardwareContext; 235 | 236 | // 237 | // -------------------------------------------------------------------- Pragmas 238 | // 239 | 240 | #pragma alloc_text(INIT, DriverEntry) 241 | #pragma alloc_text(PAGE, QcGpioEvtDriverUnload) 242 | #pragma alloc_text(PAGE, QcGpioEvtDeviceAdd) 243 | 244 | // 245 | // ------------------------------------------------------------------ Functions 246 | // 247 | 248 | NTSTATUS 249 | DriverEntry ( 250 | _In_ PDRIVER_OBJECT DriverObject, 251 | _In_ PUNICODE_STRING RegistryPath 252 | ) 253 | 254 | /*++ 255 | 256 | Routine Description: 257 | 258 | This routine is the driver initialization entry point. 259 | 260 | Arguments: 261 | 262 | DriverObject - Pointer to the driver object created by the I/O manager. 263 | 264 | RegistryPath - Pointer to the driver specific registry key. 265 | 266 | Return Value: 267 | 268 | NTSTATUS code. 269 | 270 | --*/ 271 | 272 | { 273 | 274 | WDFDRIVER Driver; 275 | WDF_DRIVER_CONFIG DriverConfig; 276 | GPIO_CLIENT_REGISTRATION_PACKET RegistrationPacket; 277 | NTSTATUS Status; 278 | 279 | // 280 | // Initialize the driver configuration structure. 281 | // 282 | 283 | WDF_DRIVER_CONFIG_INIT(&DriverConfig, QcGpioEvtDeviceAdd); 284 | DriverConfig.EvtDriverUnload = QcGpioEvtDriverUnload; 285 | 286 | // 287 | // Create a framework driver object to represent our driver. 288 | // 289 | 290 | Status = WdfDriverCreate(DriverObject, 291 | RegistryPath, 292 | WDF_NO_OBJECT_ATTRIBUTES, 293 | &DriverConfig, 294 | &Driver); 295 | 296 | if (!NT_SUCCESS(Status)) { 297 | goto DriverEntryEnd; 298 | } 299 | 300 | // 301 | // Initialize the client driver registration packet. 302 | // 303 | 304 | RtlZeroMemory(&RegistrationPacket, sizeof(GPIO_CLIENT_REGISTRATION_PACKET)); 305 | RegistrationPacket.Version = GPIO_CLIENT_VERSION; 306 | RegistrationPacket.Size = sizeof(GPIO_CLIENT_REGISTRATION_PACKET); 307 | 308 | // 309 | // Initialize the device context size. 310 | // 311 | 312 | RegistrationPacket.ControllerContextSize = sizeof(SIM_GPIO_CONTEXT); 313 | 314 | // 315 | // General interfaces. 316 | // 317 | 318 | RegistrationPacket.CLIENT_PrepareController = QcGpioPrepareController; 319 | RegistrationPacket.CLIENT_QueryControllerBasicInformation = 320 | QcGpioQueryControllerBasicInformation; 321 | 322 | // 323 | // The query/set handler is required in this sample only if F-state 324 | // power management is enabled to indicate which banks support f-state 325 | // based power maanagement. 326 | // 327 | 328 | #ifdef ENABLE_F_STATE_POWER_MGMT 329 | 330 | RegistrationPacket.CLIENT_QuerySetControllerInformation = 331 | QcGpioQuerySetControllerInformation; 332 | 333 | #endif 334 | 335 | RegistrationPacket.CLIENT_StartController = QcGpioStartController; 336 | RegistrationPacket.CLIENT_StopController = QcGpioStopController; 337 | RegistrationPacket.CLIENT_ReleaseController = QcGpioReleaseController; 338 | 339 | // 340 | // Interrupt enable and disable handlers. 341 | // 342 | 343 | RegistrationPacket.CLIENT_DisableInterrupt = QcGpioDisableInterrupt; 344 | RegistrationPacket.CLIENT_EnableInterrupt = QcGpioEnableInterrupt; 345 | 346 | // 347 | // Interrupt mask, unmask and reconfigure interrupt handlers. 348 | // 349 | 350 | RegistrationPacket.CLIENT_MaskInterrupts = QcGpioMaskInterrupts; 351 | RegistrationPacket.CLIENT_UnmaskInterrupt = QcGpioUnmaskInterrupt; 352 | RegistrationPacket.CLIENT_ReconfigureInterrupt = QcGpioReconfigureInterrupt; 353 | 354 | // 355 | // Handlers to query active/enabled interrupts and clear active interrupts. 356 | // 357 | 358 | RegistrationPacket.CLIENT_ClearActiveInterrupts = QcGpioClearActiveInterrupts; 359 | RegistrationPacket.CLIENT_QueryActiveInterrupts = QcGpioQueryActiveInterrupts; 360 | RegistrationPacket.CLIENT_QueryEnabledInterrupts = QcGpioQueryEnabledInterrupts; 361 | 362 | // 363 | // Handlers for GPIO I/O operations. 364 | // 365 | 366 | RegistrationPacket.CLIENT_ConnectIoPins = QcGpioConnectIoPins; 367 | RegistrationPacket.CLIENT_DisconnectIoPins = QcGpioDisconnectIoPins; 368 | RegistrationPacket.CLIENT_ReadGpioPinsUsingMask = QcGpioReadGpioPins; 369 | RegistrationPacket.CLIENT_WriteGpioPinsUsingMask = QcGpioWriteGpioPins; 370 | 371 | // 372 | // Handlers for GPIO save and restore context (if F-state power mgmt is 373 | // supported). 374 | // 375 | 376 | #ifdef ENABLE_F_STATE_POWER_MGMT 377 | 378 | RegistrationPacket.CLIENT_SaveBankHardwareContext = QcGpioSaveBankHardwareContext; 379 | RegistrationPacket.CLIENT_RestoreBankHardwareContext = QcGpioRestoreBankHardwareContext; 380 | 381 | #endif 382 | 383 | // 384 | // Register the QcGPIO client driver with the GPIO class extension. 385 | // 386 | 387 | Status = GPIO_CLX_RegisterClient(Driver, &RegistrationPacket, RegistryPath); 388 | 389 | DriverEntryEnd: 390 | return Status; 391 | } 392 | 393 | VOID 394 | QcGpioEvtDriverUnload ( 395 | _In_ WDFDRIVER Driver 396 | ) 397 | 398 | /*++ 399 | 400 | Routine Description: 401 | 402 | This routine is called by WDF to allow final cleanup prior to unloading the 403 | QcGPIO client driver. This routine unregisters the client driver from the 404 | class extension. 405 | 406 | Arguments: 407 | 408 | Driver - Supplies a handle to a framework driver object. 409 | 410 | Return Value: 411 | 412 | None. 413 | 414 | --*/ 415 | 416 | { 417 | 418 | NTSTATUS Status; 419 | 420 | PAGED_CODE(); 421 | 422 | Status = GPIO_CLX_UnregisterClient(Driver); 423 | NT_ASSERT(NT_SUCCESS(Status)); 424 | } 425 | 426 | NTSTATUS 427 | QcGpioEvtDeviceAdd ( 428 | _In_ WDFDRIVER Driver, 429 | _Inout_ PWDFDEVICE_INIT DeviceInit 430 | ) 431 | 432 | /*++ 433 | 434 | Routine Description: 435 | 436 | This routine is the AddDevice entry point for the client driver. This 437 | routine is called by the framework in response to AddDevice call from the 438 | PnP manager. It will create and initialize the device object to represent 439 | a new instance of the simulated GPIO controller. 440 | 441 | Arguments: 442 | 443 | Driver - Supplies a handle to the driver object created in DriverEntry. 444 | 445 | DeviceInit - Supplies a pointer to a framework-allocated WDFDEVICE_INIT 446 | structure. 447 | 448 | Return Value: 449 | 450 | NTSTATUS code. 451 | 452 | --*/ 453 | 454 | { 455 | 456 | WDFDEVICE Device; 457 | WDF_OBJECT_ATTRIBUTES FdoAttributes; 458 | NTSTATUS Status; 459 | 460 | PAGED_CODE(); 461 | 462 | // 463 | // Call the GPIO class extension's pre-device create interface. 464 | // 465 | 466 | Status = GPIO_CLX_ProcessAddDevicePreDeviceCreate(Driver, 467 | DeviceInit, 468 | &FdoAttributes); 469 | if (!NT_SUCCESS(Status)) { 470 | goto EvtDeviceAddEnd; 471 | } 472 | 473 | // 474 | // Call the framework to create the device and attach it to the lower stack. 475 | // 476 | 477 | Status = WdfDeviceCreate(&DeviceInit, &FdoAttributes, &Device); 478 | if (!NT_SUCCESS(Status)) { 479 | goto EvtDeviceAddEnd; 480 | } 481 | 482 | // 483 | // Call the GPIO class extension's post-device create interface. 484 | // 485 | 486 | Status = GPIO_CLX_ProcessAddDevicePostDeviceCreate(Driver, Device); 487 | if (!NT_SUCCESS(Status)) { 488 | goto EvtDeviceAddEnd; 489 | } 490 | 491 | EvtDeviceAddEnd: 492 | return Status; 493 | } 494 | 495 | _IRQL_requires_(PASSIVE_LEVEL) 496 | VOID 497 | QcGpiopUnmapControllerBase ( 498 | _In_ PSIM_GPIO_CONTEXT GpioContext 499 | ) 500 | 501 | /*++ 502 | 503 | Routine Description: 504 | 505 | This routine releases the memory mapping for the GPIO controller's 506 | registers, if one has been established. 507 | 508 | N.B. This function is not marked pageable because this function is in 509 | the device power down path. 510 | 511 | Arguments: 512 | 513 | Context - Supplies a pointer to the GPIO client driver's device extension. 514 | 515 | Return Value: 516 | 517 | NTSTATUS code. 518 | 519 | --*/ 520 | 521 | { 522 | 523 | if ((GpioContext->ControllerBase != NULL) && 524 | (GpioContext->ControllerBase != GlobalGpioRegisters)) { 525 | MmUnmapIoSpace(GpioContext->ControllerBase, GpioContext->Length); 526 | GpioContext->ControllerBase = NULL; 527 | } 528 | } 529 | 530 | // 531 | // ---------------------------------------------------------- General intefaces 532 | // 533 | 534 | _Must_inspect_result_ 535 | _IRQL_requires_(PASSIVE_LEVEL) 536 | NTSTATUS 537 | QcGpioPrepareController ( 538 | _In_ WDFDEVICE Device, 539 | _In_ PVOID Context, 540 | _In_ WDFCMRESLIST ResourcesRaw, 541 | _In_ WDFCMRESLIST ResourcesTranslated 542 | ) 543 | 544 | /*++ 545 | 546 | Routine Description: 547 | 548 | This routine is called by the GPIO class extension to prepare the 549 | simulated GPIO controller for use. 550 | 551 | N.B. This function is not marked pageable because this function is in 552 | the device power up path. 553 | 554 | Arguments: 555 | 556 | Context - Supplies a pointer to the GPIO client driver's device extension. 557 | 558 | ResourcesRaw - Supplies a handle to a collection of framework resource 559 | objects. This collection identifies the raw (bus-relative) hardware 560 | resources that have been assigned to the device. 561 | 562 | ResourcesTranslated - Supplies a handle to a collection of framework 563 | resource objects. This collection identifies the translated 564 | (system-physical) hardware resources that have been assigned to the 565 | device. The resources appear from the CPU's point of view. 566 | 567 | Return Value: 568 | 569 | NTSTATUS code. 570 | 571 | --*/ 572 | 573 | { 574 | 575 | BANK_ID BankId; 576 | PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; 577 | PSIM_GPIO_BANK GpioBank; 578 | PSIM_GPIO_CONTEXT GpioContext; 579 | ULONG Index; 580 | ULONG InterruptResourceCount; 581 | ULONG MemoryResourceCount; 582 | ULONG RequiredSize; 583 | ULONG Offset; 584 | ULONG ResourceCount; 585 | NTSTATUS Status; 586 | 587 | UNREFERENCED_PARAMETER(Device); 588 | UNREFERENCED_PARAMETER(ResourcesRaw); 589 | 590 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 591 | RtlZeroMemory(GpioContext, sizeof(SIM_GPIO_CONTEXT)); 592 | GpioContext->TotalPins = SIM_GPIO_TOTAL_PINS; 593 | 594 | // 595 | // Walk through the resource list and map all the resources. Atleast one 596 | // memory resource and one interrupt resource is expected. The resources 597 | // are described in the ACPI namespace. 598 | // 599 | 600 | InterruptResourceCount = 0; 601 | MemoryResourceCount = 0; 602 | ResourceCount = WdfCmResourceListGetCount(ResourcesTranslated); 603 | Status = STATUS_SUCCESS; 604 | for (Index = 0; Index < ResourceCount; Index += 1) { 605 | Descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, Index); 606 | switch(Descriptor->Type) { 607 | 608 | // 609 | // The memory resource supplies the physical register base for the GPIO 610 | // controller. Map it virtually as non-cached. 611 | // 612 | 613 | case CmResourceTypeMemory: 614 | if (MemoryResourceCount == 0) { 615 | RequiredSize = SIM_GPIO_TOTAL_BANKS * sizeof(SIM_GPIO_REGISTERS); 616 | 617 | NT_ASSERT(Descriptor->u.Memory.Length >= RequiredSize); 618 | 619 | if (Descriptor->u.Memory.Length < RequiredSize) { 620 | Status = STATUS_UNSUCCESSFUL; 621 | break; 622 | } 623 | 624 | GpioContext->PhysicalBaseAddress = Descriptor->u.Memory.Start; 625 | GpioContext->ControllerBase = 626 | (PSIM_GPIO_REGISTERS)MmMapIoSpaceEx( 627 | Descriptor->u.Memory.Start, 628 | RequiredSize, 629 | PAGE_NOCACHE | PAGE_READWRITE); 630 | 631 | // 632 | // Fail initialization if mapping of the memory region failed. 633 | // 634 | 635 | if (GpioContext->ControllerBase == NULL) { 636 | Status = STATUS_UNSUCCESSFUL; 637 | } 638 | 639 | GpioContext->Length = RequiredSize; 640 | } 641 | 642 | MemoryResourceCount += 1; 643 | break; 644 | 645 | // 646 | // IO port resources are unexpected, fail initialization. 647 | // 648 | 649 | case CmResourceTypePort: 650 | Status = STATUS_UNSUCCESSFUL; 651 | break; 652 | 653 | // 654 | // Interrupt resource which supplies the GPIO controller interrupt 655 | // (that connects to the GIC). 656 | // 657 | // N.B. Connecting of the interrupt is handled by the GPIO class 658 | // extension. Only ensure that appropriate number of interrupts 659 | // were described. 660 | // 661 | 662 | case CmResourceTypeInterrupt: 663 | InterruptResourceCount += 1; 664 | break; 665 | 666 | // 667 | // This could be device-private type added by the underlying bus 668 | // driver. Do not filter or alter this resource information. 669 | // 670 | 671 | default: 672 | break; 673 | } 674 | 675 | if (!NT_SUCCESS(Status)) { 676 | goto PrepareControllerEnd; 677 | } 678 | } 679 | 680 | // 681 | // NOTE: As QcGPIO is not a real hardware device, it doesn't really have 682 | // any physical registers. For test purposes, fake the GPIO registers 683 | // using a software defined global structure. This should NOT be done 684 | // for a real GPIO controller 685 | // 686 | // BEGIN: QCGPIO HACK. 687 | // 688 | 689 | if (MemoryResourceCount == 0) { 690 | GpioContext->ControllerBase = GlobalGpioRegisters; 691 | MemoryResourceCount = 1; 692 | } 693 | 694 | // 695 | // END: QCGPIO HACK. 696 | // 697 | 698 | // 699 | // Fail initialization if minimum number of interrupt 700 | // and memory resources were not described correctly. 701 | // 702 | 703 | if ((InterruptResourceCount < SIM_GPIO_TOTAL_BANKS) || 704 | (MemoryResourceCount < 1)) { 705 | Status = STATUS_UNSUCCESSFUL; 706 | goto PrepareControllerEnd; 707 | } 708 | 709 | // 710 | // Initialize the base address of registers per bank. 711 | // 712 | 713 | for (BankId = 0; BankId < SIM_GPIO_TOTAL_BANKS; BankId += 1) { 714 | GpioBank = &GpioContext->Banks[BankId]; 715 | Offset = BankId * sizeof(SIM_GPIO_REGISTERS); 716 | GpioBank->Registers = Add2Ptr(GpioContext->ControllerBase, Offset); 717 | GpioBank->Length = sizeof(SIM_GPIO_REGISTERS); 718 | } 719 | 720 | PrepareControllerEnd: 721 | if (!NT_SUCCESS(Status)) { 722 | QcGpiopUnmapControllerBase(GpioContext); 723 | } 724 | 725 | return Status; 726 | } 727 | 728 | _Must_inspect_result_ 729 | _IRQL_requires_(PASSIVE_LEVEL) 730 | NTSTATUS 731 | QcGpioReleaseController ( 732 | _In_ WDFDEVICE Device, 733 | _In_ PVOID Context 734 | ) 735 | 736 | /*++ 737 | 738 | Routine Description: 739 | 740 | This routine is called by the GPIO class extension to uninitialize the GPIO 741 | controller. 742 | 743 | N.B. This function is not marked pageable because this function is in 744 | the device power down path. 745 | 746 | Arguments: 747 | 748 | Context - Supplies a pointer to the GPIO client driver's device extension. 749 | 750 | Return Value: 751 | 752 | NTSTATUS code. 753 | 754 | --*/ 755 | 756 | { 757 | 758 | UNREFERENCED_PARAMETER(Device); 759 | UNREFERENCED_PARAMETER(Context); 760 | 761 | // 762 | // Release the mappings established in the initialize callback. 763 | // 764 | // N.B. Disconnecting of the interrupt is handled by the GPIO class 765 | // extension. 766 | // 767 | 768 | QcGpiopUnmapControllerBase((PSIM_GPIO_CONTEXT)Context); 769 | return STATUS_SUCCESS; 770 | } 771 | 772 | _Must_inspect_result_ 773 | _IRQL_requires_(PASSIVE_LEVEL) 774 | NTSTATUS 775 | QcGpioQueryControllerBasicInformation ( 776 | _In_ PVOID Context, 777 | _Out_ PCLIENT_CONTROLLER_BASIC_INFORMATION ControllerInformation 778 | ) 779 | 780 | /*++ 781 | 782 | Routine Description: 783 | 784 | This routine returns the GPIO controller's attributes to the class extension. 785 | 786 | N.B. This function is not marked pageable because this function is in 787 | the device power up path. 788 | 789 | Arguments: 790 | 791 | Context - Supplies a pointer to the GPIO client driver's device extension. 792 | 793 | ControllerInformation - Supplies a pointer to a buffer that receives 794 | controller's information. 795 | 796 | Return Value: 797 | 798 | NTSTATUS code. 799 | 800 | --*/ 801 | 802 | { 803 | 804 | PSIM_GPIO_CONTEXT GpioContext; 805 | 806 | ControllerInformation->Version = GPIO_CONTROLLER_BASIC_INFORMATION_VERSION; 807 | ControllerInformation->Size = sizeof(CLIENT_CONTROLLER_BASIC_INFORMATION); 808 | 809 | // 810 | // Specify the number of pins on the QcGPIO controller. 811 | // 812 | 813 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 814 | ControllerInformation->TotalPins = GpioContext->TotalPins; 815 | ControllerInformation->NumberOfPinsPerBank = SIM_GPIO_PINS_PER_BANK; 816 | 817 | // 818 | // Indicate that the GPIO controller is memory-mapped and thus can be 819 | // manipulated at DIRQL. 820 | // 821 | // N.B. If the GPIO controller is off-SOC behind some serial bus like 822 | // I2C or SPI, then this field must be set to FALSE. 823 | // 824 | 825 | ControllerInformation->Flags.MemoryMappedController = TRUE; 826 | 827 | // 828 | // Indicate that the H/W registers used for I/O can be accessed seperately 829 | // from the registers used for interrupt processing. 830 | // 831 | // N.B.: Setting this flag to TRUE will cause the GPIO class extension 832 | // to optimize I/O processing by skipping the acquisition of 833 | // interrupt-related locks in I/O paths. Make sure the GPIO controller 834 | // H/W can support simultaneous I/O and interrupt processing. Otherwise 835 | // unpredictable race conditions may occur! 836 | // 837 | 838 | ControllerInformation->Flags.IndependentIoHwSupported = TRUE; 839 | 840 | // 841 | // Indicate that status register must be cleared explicitly. 842 | // 843 | 844 | ControllerInformation->Flags.ActiveInterruptsAutoClearOnRead = 0; 845 | 846 | // 847 | // Indicate that the client driver would like to receive IO requests as a 848 | // set of bitmasks as that maps directly to the register operations. 849 | // 850 | 851 | ControllerInformation->Flags.FormatIoRequestsAsMasks = 1; 852 | 853 | // 854 | // Indicate that the GPIO controller does not support controller-level 855 | // D-state power management. 856 | // 857 | 858 | ControllerInformation->Flags.DeviceIdlePowerMgmtSupported = FALSE; 859 | 860 | // 861 | // Note if bank-level F-state power management is supported, then specify 862 | // as such. Note the QuerySetControllerInformation() handler also needs to 863 | // be implemented in this case. 864 | // 865 | 866 | #ifdef ENABLE_F_STATE_POWER_MGMT 867 | 868 | ControllerInformation->Flags.BankIdlePowerMgmtSupported = TRUE; 869 | 870 | #else 871 | 872 | ControllerInformation->Flags.BankIdlePowerMgmtSupported = FALSE; 873 | 874 | #endif 875 | 876 | // 877 | // Note the IdleTimeout parameter does not need to be initialized if 878 | // D-state power management is not supported. 879 | // 880 | // ControllerInformation->IdleTimeout = IdleTimeoutDefaultValue; 881 | // 882 | 883 | // 884 | // Note if the GPIO controller does not support hardware debouncing and 885 | // software-debouncing should be used instead, set the EmulateDebouncing 886 | // flag. 887 | // 888 | // ControllerInformation->Flags.EmulateDebouncing = TRUE; 889 | // 890 | 891 | // 892 | // Indicate that the client driver prefers GPIO class extension ActiveBoth 893 | // emulation. 894 | // 895 | 896 | ControllerInformation->Flags.EmulateActiveBoth = TRUE; 897 | 898 | return STATUS_SUCCESS; 899 | } 900 | 901 | _Must_inspect_result_ 902 | _IRQL_requires_(PASSIVE_LEVEL) 903 | NTSTATUS 904 | QcGpioQuerySetControllerInformation ( 905 | _In_ PVOID Context, 906 | _In_ PCLIENT_CONTROLLER_QUERY_SET_INFORMATION_INPUT InputBuffer, 907 | _Out_opt_ PCLIENT_CONTROLLER_QUERY_SET_INFORMATION_OUTPUT OutputBuffer 908 | ) 909 | 910 | /*++ 911 | 912 | Routine Description: 913 | 914 | This routine is the generic GPIO query/set handler. Currently it only 915 | supports returning bank power information. 916 | 917 | Arguments: 918 | 919 | Context - Supplies a pointer to the GPIO client driver's device extension. 920 | 921 | InputBuffer - Supplies a pointer to a buffer that receives the parameters 922 | for the query or set operation. 923 | 924 | OutputBuffer - Supplies a pointer to the GPIO class extension allocated 925 | buffer to return the output values. Note on entry, the 926 | OutputBuffer->Size indicates how big the output buffer is. On exit, the 927 | OutputBuffer->Size indicates the filled-in size or required size. 928 | 929 | Return Value: 930 | 931 | NTSTATUS code. 932 | 933 | --*/ 934 | 935 | { 936 | 937 | PPO_FX_COMPONENT_IDLE_STATE F1Parameters; 938 | NTSTATUS Status; 939 | 940 | UNREFERENCED_PARAMETER(Context); 941 | 942 | if((InputBuffer == NULL) || (OutputBuffer == NULL)) { 943 | Status = STATUS_NOT_SUPPORTED; 944 | goto QuerySetControllerInformationEnd; 945 | } 946 | 947 | if (InputBuffer->RequestType != QueryBankPowerInformation) { 948 | Status = STATUS_NOT_SUPPORTED; 949 | goto QuerySetControllerInformationEnd; 950 | } 951 | 952 | // 953 | // Set the version and size of the output buffer. 954 | // 955 | 956 | OutputBuffer->Version = GPIO_BANK_POWER_INFORMATION_OUTPUT_VERSION; 957 | OutputBuffer->Size = sizeof(CLIENT_CONTROLLER_QUERY_SET_INFORMATION_OUTPUT); 958 | 959 | // 960 | // Mark the given bank (InputBuffer->BankPowerInformation.BankId) as 961 | // supporting F1 state. Since all banks support it, the BankId is not 962 | // checked. 963 | // 964 | 965 | OutputBuffer->BankPowerInformation.F1StateSupported = TRUE; 966 | 967 | // 968 | // Supply the attributes for the F1 power state. 969 | // 970 | 971 | F1Parameters = &OutputBuffer->BankPowerInformation.F1IdleStateParameters; 972 | F1Parameters->NominalPower = SIM_GPIO_F1_NOMINAL_POWER; 973 | F1Parameters->ResidencyRequirement = 974 | WDF_ABS_TIMEOUT_IN_SEC(SIM_GPIO_F1_RESIDENCY); 975 | 976 | F1Parameters->TransitionLatency = 977 | WDF_ABS_TIMEOUT_IN_SEC(SIM_GPIO_F1_TRANSITION); 978 | 979 | Status = STATUS_SUCCESS; 980 | 981 | QuerySetControllerInformationEnd: 982 | return Status; 983 | } 984 | 985 | 986 | _Must_inspect_result_ 987 | _IRQL_requires_(PASSIVE_LEVEL) 988 | NTSTATUS 989 | QcGpioStartController ( 990 | _In_ PVOID Context, 991 | _In_ BOOLEAN RestoreContext, 992 | _In_ WDF_POWER_DEVICE_STATE PreviousPowerState 993 | ) 994 | 995 | /*++ 996 | 997 | Routine Description: 998 | 999 | This routine starts the simulated GPIO controller. This routine is 1000 | responsible for configuring all the pins to their default modes. 1001 | 1002 | N.B. This function is not marked pageable because this function is in 1003 | the device power up path. It is called at PASSIVE_IRQL though. 1004 | 1005 | Arguments: 1006 | 1007 | Context - Supplies a pointer to the GPIO client driver's device extension. 1008 | 1009 | RestoreContext - Supplies a flag that indicates whether the client driver 1010 | should restore the GPIO controller state to a previously saved state 1011 | or not. 1012 | 1013 | PreviousPowerState - Supplies the device power state that the device was in 1014 | before this transition to D0. 1015 | 1016 | Return Value: 1017 | 1018 | NTSTATUS code. 1019 | 1020 | --*/ 1021 | 1022 | { 1023 | 1024 | BANK_ID BankId; 1025 | PSIM_GPIO_BANK GpioBank; 1026 | PSIM_GPIO_CONTEXT GpioContext; 1027 | ULONG PinValue; 1028 | GPIO_SAVE_RESTORE_BANK_HARDWARE_CONTEXT_PARAMETERS RestoreParameters; 1029 | PSIM_GPIO_REGISTERS QcGpioRegisters; 1030 | 1031 | UNREFERENCED_PARAMETER(PreviousPowerState); 1032 | 1033 | // 1034 | // Perform all the steps necessary to start the device. 1035 | // 1036 | 1037 | // 1038 | // If restore context is FALSE, then this is initial transition into D0 1039 | // power state for this controller. In such case, disable any interrupts 1040 | // that may have been left enabled (e.g. perhaps by FW, previous D0 -> Dx 1041 | // transition etc.) Otherwise, such interrupts could trigger an interrupt 1042 | // storm if they were to assert without any driver being registered to 1043 | // handle such interrupts. 1044 | // 1045 | // If restore context is TRUE, then this is a transition into D0 power 1046 | // state from a lower power Dx state. In such case, restore the context 1047 | // that was present before the controller transitioned into the lower 1048 | // power state. 1049 | // 1050 | 1051 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 1052 | if (RestoreContext == FALSE) { 1053 | for (BankId = 0; BankId < SIM_GPIO_TOTAL_BANKS; BankId += 1) { 1054 | GpioBank = &GpioContext->Banks[BankId]; 1055 | QcGpioRegisters = GpioBank->Registers; 1056 | 1057 | // 1058 | // Disable all interrupts on this bank by clearing the enable 1059 | // register. 1060 | // 1061 | 1062 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->EnableRegister); 1063 | if (PinValue > 0) { 1064 | PinValue = 0; 1065 | WRITE_REGISTER_ULONG(&QcGpioRegisters->EnableRegister, 1066 | PinValue); 1067 | } 1068 | } 1069 | 1070 | } else { 1071 | 1072 | // 1073 | // Restoring the controller state involves restoring the state of 1074 | // each QcGPIO bank. 1075 | // 1076 | 1077 | for (BankId = 0; BankId < SIM_GPIO_TOTAL_BANKS; BankId += 1) { 1078 | RestoreParameters.BankId = BankId; 1079 | RestoreParameters.State = PreviousPowerState; 1080 | QcGpioRestoreBankHardwareContext(Context, &RestoreParameters); 1081 | } 1082 | } 1083 | 1084 | return STATUS_SUCCESS; 1085 | } 1086 | 1087 | _IRQL_requires_(PASSIVE_LEVEL) 1088 | NTSTATUS 1089 | QcGpioStopController ( 1090 | _In_ PVOID Context, 1091 | _In_ BOOLEAN SaveContext, 1092 | _In_ WDF_POWER_DEVICE_STATE TargetState 1093 | ) 1094 | 1095 | /*++ 1096 | 1097 | Routine Description: 1098 | 1099 | This routine stops the GPIO controller. This routine is responsible for 1100 | resetting all the pins to their default modes. 1101 | 1102 | N.B. This function is not marked pageable because this function is in 1103 | the device power down path. 1104 | 1105 | Arguments: 1106 | 1107 | Context - Supplies a pointer to the GPIO client driver's device extension. 1108 | 1109 | SaveContext - Supplies a flag that indicates whether the client driver 1110 | should save the GPIO controller state or not. The state may need 1111 | to be restored when the controller is restarted. 1112 | 1113 | TargetState - Supplies the device power state which the device will be put 1114 | in once the callback is complete. 1115 | 1116 | Return Value: 1117 | 1118 | NTSTATUS code. 1119 | 1120 | --*/ 1121 | 1122 | { 1123 | 1124 | 1125 | BANK_ID BankId; 1126 | PSIM_GPIO_CONTEXT GpioContext; 1127 | GPIO_SAVE_RESTORE_BANK_HARDWARE_CONTEXT_PARAMETERS SaveParameters; 1128 | 1129 | UNREFERENCED_PARAMETER(TargetState); 1130 | 1131 | // 1132 | // Perform all the steps necessary to stop the device. 1133 | // 1134 | 1135 | // 1136 | // If save context is FALSE, then this is a final transition into D3/off 1137 | // power state. Hence saving of context is not necessary. 1138 | // 1139 | // If save context is TRUE, then this is a transition into a lower power 1140 | // Dx state. In such case, save the context as it will need to be 1141 | // restored when the device is brought back to D0 (i.e. ON) power state. 1142 | // 1143 | 1144 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 1145 | if (SaveContext == TRUE) { 1146 | for (BankId = 0; BankId < SIM_GPIO_TOTAL_BANKS; BankId += 1) { 1147 | SaveParameters.BankId = BankId; 1148 | SaveParameters.State = TargetState; 1149 | QcGpioSaveBankHardwareContext(Context, &SaveParameters); 1150 | } 1151 | } 1152 | 1153 | return STATUS_SUCCESS; 1154 | } 1155 | 1156 | // 1157 | // --------------------------------------------------------- Interrupt Handlers 1158 | // 1159 | 1160 | _Must_inspect_result_ 1161 | _IRQL_requires_(PASSIVE_LEVEL) 1162 | NTSTATUS 1163 | QcGpioEnableInterrupt ( 1164 | _In_ PVOID Context, 1165 | _In_ PGPIO_ENABLE_INTERRUPT_PARAMETERS EnableParameters 1166 | ) 1167 | 1168 | /*++ 1169 | 1170 | Routine Description: 1171 | 1172 | This routine configures the supplied pin for interrupt. 1173 | 1174 | N.B. This routine is called from within a regular thread context (i.e., 1175 | non-interrupt context) by the class extension. Thus the interrupt lock 1176 | needs to be explicitly acquired for memory-mapped GPIO controllers 1177 | prior to manipulating any device state that is also affected from a 1178 | routine called within the interrupt context. 1179 | 1180 | Arguments: 1181 | 1182 | Context - Supplies a pointer to the GPIO client driver's device extension. 1183 | 1184 | EnableParameters - Supplies a pointer to a structure containing enable 1185 | operation parameters. Fields are: 1186 | 1187 | BankId - Supplies the ID for the GPIO bank. 1188 | 1189 | PinNumber - Supplies the interrupt line that should be enabled. The pin 1190 | number is relative to the bank. 1191 | 1192 | Flags - Supplies flags controlling the enable operation. Currently 1193 | no flags are defined. 1194 | 1195 | InterruptMode - Supplies the trigger mode (edge or level) configured for 1196 | this interrupt when it was enabled. 1197 | 1198 | Polarity - Supplies the polarity (active low or active high) configured 1199 | for this interrupt when it was enabled. 1200 | Note: For edge-triggered interrupts, ActiveLow corresponds to the 1201 | falling edge; ActiveHigh corresponds to the rising edge. 1202 | 1203 | PullConfiguration - Supplies the pin pull-up/pull-down configuration. 1204 | 1205 | DebouceTimeout - Supplies the debounce timeout to be applied. The 1206 | field is in 100th of milli-seconds (i.e., 5.84ms will be supplied 1207 | as 584). Default value is zero, which implies, no debounce. 1208 | 1209 | VendorData - Supplies an optional pointer to a buffer containing the 1210 | vendor data supplied in the GPIO descriptor. This field will be 1211 | NULL if no vendor data was supplied. This buffer is read-only. 1212 | 1213 | VendorDataLength - Supplies the length of the vendor data buffer. 1214 | 1215 | Return Value: 1216 | 1217 | NTSTATUS code. 1218 | 1219 | Environment: 1220 | 1221 | Entry IRQL: PASSIVE_LEVEL. 1222 | 1223 | Synchronization: The GPIO class extension will synchronize this call 1224 | against other passive-level interrupt callbacks (e.g. enable/disable/ 1225 | unmask) and IO callbacks. 1226 | 1227 | --*/ 1228 | 1229 | { 1230 | 1231 | BANK_ID BankId; 1232 | PSIM_GPIO_BANK GpioBank; 1233 | PSIM_GPIO_CONTEXT GpioContext; 1234 | ULONG Index; 1235 | PIN_NUMBER PinNumber; 1236 | ULONG PinValue; 1237 | PIN_NUMBER ShiftBits; 1238 | PSIM_GPIO_REGISTERS QcGpioRegisters; 1239 | NTSTATUS Status; 1240 | 1241 | // 1242 | // If the polarity is not supported, then bail out. Note the interrupt 1243 | // polarity cannot be InterruptActiveBoth as this sample uses ActiveBoth 1244 | // emulation. 1245 | // 1246 | 1247 | if ((EnableParameters->Polarity != InterruptActiveHigh) && 1248 | (EnableParameters->Polarity != InterruptActiveLow)) { 1249 | 1250 | Status = STATUS_NOT_SUPPORTED; 1251 | goto EnableInterruptEnd; 1252 | } 1253 | 1254 | BankId = EnableParameters->BankId; 1255 | PinNumber = EnableParameters->PinNumber; 1256 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 1257 | GpioBank = &GpioContext->Banks[BankId]; 1258 | QcGpioRegisters = GpioBank->Registers; 1259 | Status = STATUS_SUCCESS; 1260 | 1261 | // 1262 | // The interrupt enable register/bitmap may be manipulated from within the 1263 | // interrupt context. Hence updates to it must be synchronized using the 1264 | // interrupt lock. 1265 | // 1266 | 1267 | GPIO_CLX_AcquireInterruptLock(Context, BankId); 1268 | 1269 | // 1270 | // Set the mode register. If the interrupt is Level then set the bit; 1271 | // otherwise, clear it (edge-triggered). 1272 | // 1273 | 1274 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->ModeRegister); 1275 | if (EnableParameters->InterruptMode == LevelSensitive) { 1276 | PinValue |= (1 << PinNumber); 1277 | } else { 1278 | PinValue &= ~(1 << PinNumber); 1279 | } 1280 | 1281 | WRITE_REGISTER_ULONG(&QcGpioRegisters->ModeRegister, PinValue); 1282 | 1283 | // 1284 | // Set the polarity register. There are two bits for each pin. If the 1285 | // interrupt is ActiveHigh (or Rising-edge) then set it to 0x1. 1286 | // 1287 | 1288 | Index = PinNumber / 16; 1289 | ShiftBits = (PinNumber % 16) * 2; 1290 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->PolarityRegister[Index]); 1291 | switch (EnableParameters->Polarity) { 1292 | 1293 | case InterruptActiveHigh: 1294 | PinValue &= ~(0x3 << ShiftBits); 1295 | PinValue |= (1 << ShiftBits); 1296 | break; 1297 | 1298 | case InterruptActiveLow: 1299 | PinValue &= ~(0x3 << ShiftBits); 1300 | break; 1301 | } 1302 | 1303 | WRITE_REGISTER_ULONG(&QcGpioRegisters->PolarityRegister[Index], PinValue); 1304 | 1305 | // 1306 | // NOTE: If the GPIO controller supports a separate set of mask registers, 1307 | // then any stale value must be cleared here. QcGPIO controller 1308 | // doesn't and hence this step is skipped here. 1309 | // 1310 | 1311 | // 1312 | // Clear the corresponding status bit first to ignore any stale value. 1313 | // 1314 | 1315 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->StatusRegister); 1316 | PinValue &= ~(1 << PinNumber); 1317 | WRITE_REGISTER_ULONG(&QcGpioRegisters->StatusRegister, PinValue); 1318 | 1319 | // 1320 | // Enable the interrupt by setting the bit in the interrupt enable register. 1321 | // 1322 | 1323 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->EnableRegister); 1324 | PinValue |= (1 << PinNumber); 1325 | WRITE_REGISTER_ULONG(&QcGpioRegisters->EnableRegister, PinValue); 1326 | 1327 | // 1328 | // Release the interrupt lock. 1329 | // 1330 | 1331 | GPIO_CLX_ReleaseInterruptLock(Context, BankId); 1332 | 1333 | Status = STATUS_SUCCESS; 1334 | 1335 | EnableInterruptEnd: 1336 | return Status; 1337 | } 1338 | 1339 | _Must_inspect_result_ 1340 | _IRQL_requires_(PASSIVE_LEVEL) 1341 | NTSTATUS 1342 | QcGpioDisableInterrupt ( 1343 | _In_ PVOID Context, 1344 | _In_ PGPIO_DISABLE_INTERRUPT_PARAMETERS DisableParameters 1345 | ) 1346 | 1347 | /*++ 1348 | 1349 | Routine Description: 1350 | 1351 | This routine disables the supplied pin from interrupting. 1352 | 1353 | This routine is not marked PAGED as it may be called before/after 1354 | the boot device is in D0/D3 if boot device has GPIO dependencies. 1355 | 1356 | N.B. This routine is called from within a regular thread context (i.e., 1357 | non-interrupt context) by the class extension. Thus the interrupt lock 1358 | needs to be explicitly acquired prior to manipulating the device state. 1359 | 1360 | Arguments: 1361 | 1362 | Context - Supplies a pointer to the GPIO client driver's device extension. 1363 | 1364 | DisableParameters - Supplies a pointer to a structure supplying the 1365 | parameters for disabling the interrupt. Fields are: 1366 | 1367 | BankId - Supplies the ID for the GPIO bank. 1368 | 1369 | PinNumber - Supplies the interrupt line that should be disabled. The pin 1370 | number is relative to the bank. 1371 | 1372 | Flags - Supplies flags controlling the disable operation. Currently 1373 | no flags are defined. 1374 | 1375 | Return Value: 1376 | 1377 | NTSTATUS code (STATUS_SUCCESS always for memory-mapped GPIO controllers). 1378 | 1379 | Environment: 1380 | 1381 | Entry IRQL: PASSIVE_LEVEL. 1382 | 1383 | Synchronization: The GPIO class extension will synchronize this call 1384 | against other passive-level interrupt callbacks (e.g. enable/disable/ 1385 | unmask) and IO callbacks. 1386 | 1387 | --*/ 1388 | 1389 | { 1390 | 1391 | BANK_ID BankId; 1392 | PSIM_GPIO_BANK GpioBank; 1393 | PSIM_GPIO_CONTEXT GpioContext; 1394 | ULONG PinValue; 1395 | PSIM_GPIO_REGISTERS QcGpioRegisters; 1396 | 1397 | BankId = DisableParameters->BankId; 1398 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 1399 | GpioBank = &GpioContext->Banks[BankId]; 1400 | QcGpioRegisters = GpioBank->Registers; 1401 | 1402 | // 1403 | // The interrupt enable register may be manipulated from within the 1404 | // interrupt context. Hence updates to it must be synchronized using the 1405 | // interrupt lock. 1406 | // 1407 | 1408 | GPIO_CLX_AcquireInterruptLock(Context, BankId); 1409 | 1410 | // 1411 | // Disable the interrupt by clearing the bit in the interrupt enable 1412 | // register. 1413 | // 1414 | 1415 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->EnableRegister); 1416 | PinValue &= ~(1 << DisableParameters->PinNumber); 1417 | WRITE_REGISTER_ULONG(&QcGpioRegisters->EnableRegister, PinValue); 1418 | 1419 | GPIO_CLX_ReleaseInterruptLock(Context, BankId); 1420 | 1421 | return STATUS_SUCCESS; 1422 | } 1423 | 1424 | _Must_inspect_result_ 1425 | _IRQL_requires_same_ 1426 | NTSTATUS 1427 | QcGpioMaskInterrupts ( 1428 | _In_ PVOID Context, 1429 | _In_ PGPIO_MASK_INTERRUPT_PARAMETERS MaskParameters 1430 | ) 1431 | 1432 | /*++ 1433 | 1434 | Routine Description: 1435 | 1436 | This routine invokes masks the supplied pin from interrupting. 1437 | 1438 | Arguments: 1439 | 1440 | Context - Supplies a pointer to the GPIO client driver's device extension. 1441 | 1442 | MaskParameters - Supplies a pointer to a structure containing mask 1443 | operation parameters. Fields are: 1444 | 1445 | BankId - Supplies the ID for the GPIO bank. 1446 | 1447 | PinMask - Supplies a bitmask of pins which should be masked. If a pin 1448 | should be masked, then the corresponding bit is set in the bitmask. 1449 | 1450 | FailedMask - Supplies a bitmask of pins that failed to be masked. If 1451 | a pin could not be masked, the bit should be set in this field. 1452 | 1453 | N.B. This should only be done if for non memory-mapped controllers. 1454 | Memory-mapped controllers are never expected to fail this 1455 | operation. 1456 | 1457 | Return Value: 1458 | 1459 | NTSTATUS code (STATUS_SUCCESS always for memory-mapped GPIO controllers). 1460 | 1461 | Environment: 1462 | 1463 | Entry IRQL: DIRQL if the GPIO controller is memory-mapped; PASSIVE_LEVEL 1464 | if the controller is behind some serial-bus. 1465 | 1466 | N.B. For memory-mapped controllers, this routine is called from within 1467 | the interrupt context with the interrupt lock acquired by the class 1468 | extension. Hence the lock is not re-acquired here. 1469 | 1470 | Synchronization: The GPIO class extension will synchronize this call 1471 | against other query/clear active and enabled interrupts. 1472 | Memory-mapped GPIO controllers: 1473 | Callbacks invoked at PASSIVE_LEVEL IRQL (e.g. interrupt 1474 | enable/disable/unmask or IO operations) may be active. Those 1475 | routines should acquire the interrupt lock prior to manipulating 1476 | any state accessed from within this routine. 1477 | 1478 | Serial-accessible GPIO controllers: 1479 | This call is synchronized with all other interrupt and IO callbacks. 1480 | 1481 | --*/ 1482 | 1483 | { 1484 | 1485 | PSIM_GPIO_BANK GpioBank; 1486 | PSIM_GPIO_CONTEXT GpioContext; 1487 | ULONG PinValue; 1488 | PSIM_GPIO_REGISTERS QcGpioRegisters; 1489 | 1490 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 1491 | GpioBank = &GpioContext->Banks[MaskParameters->BankId]; 1492 | QcGpioRegisters = GpioBank->Registers; 1493 | 1494 | // 1495 | // Mask is essentially same as disable for QcGPIO controller. The 1496 | // difference between the routines is that mask callback is called at DIRQL 1497 | // and automatically synchronized with other DIRQL interrupts callbacks. 1498 | // 1499 | 1500 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->EnableRegister); 1501 | PinValue &= ~(ULONG)(MaskParameters->PinMask); 1502 | WRITE_REGISTER_ULONG(&QcGpioRegisters->EnableRegister, PinValue); 1503 | 1504 | // 1505 | // Set the bitmask of pins that could not be successfully masked. 1506 | // Since this is a memory-mapped controller, the mask operation always 1507 | // succeeds. 1508 | // 1509 | 1510 | MaskParameters->FailedMask = 0x0; 1511 | return STATUS_SUCCESS; 1512 | } 1513 | 1514 | NTSTATUS 1515 | QcGpioUnmaskInterrupt ( 1516 | _In_ PVOID Context, 1517 | _In_ PGPIO_ENABLE_INTERRUPT_PARAMETERS UnmaskParameters 1518 | ) 1519 | 1520 | /*++ 1521 | 1522 | Routine Description: 1523 | 1524 | This routine invokes unmasks the supplied interrupt pin. 1525 | 1526 | Arguments: 1527 | 1528 | Context - Supplies a pointer to the GPIO client driver's device extension. 1529 | 1530 | UnmaskParameters - Supplies a pointer to a structure containing parameters 1531 | for unmasking the interrupt. Fields are: 1532 | 1533 | BankId - Supplies the ID for the GPIO bank. 1534 | 1535 | PinNumber - Supplies the interrupt line that should be unmasked. The pin 1536 | number is relative to the bank. 1537 | 1538 | InterruptMode - Supplies the trigger mode (edge or level) configured for 1539 | this interrupt when it was enabled. 1540 | 1541 | Polarity - Supplies the polarity (active low or active high) configured 1542 | for this interrupt when it was enabled. 1543 | Note: For edge-triggered interrupts, ActiveLow corresponds to the 1544 | falling edge; ActiveHigh corresponds to the rising edge. 1545 | 1546 | PullConfiguration - Supplies the pin pull-up/pull-down configuration. 1547 | 1548 | DebouceTimeout - Supplies the debounce timeout to be applied. The 1549 | field is in 100th of milli-seconds (i.e., 5.84ms will be supplied 1550 | as 584). Default value is zero, which implies, no debounce. 1551 | 1552 | VendorData - NULL. 1553 | 1554 | VendorDataLength - 0. 1555 | 1556 | N.B. The VendorData and VendorDataLength are not supplied for unmask 1557 | operation (i.e., both fields are zero). 1558 | 1559 | Return Value: 1560 | 1561 | NTSTATUS code (STATUS_SUCCESS always for memory-mapped GPIO controllers). 1562 | 1563 | Environment: 1564 | 1565 | Entry IRQL: DIRQL if the GPIO controller is memory-mapped; PASSIVE_LEVEL 1566 | if the controller is behind some serial-bus. 1567 | 1568 | N.B. For memory-mapped controllers, this routine is called from within 1569 | the interrupt context with the interrupt lock acquired by the class 1570 | extension. Hence the lock is not re-acquired here. 1571 | 1572 | Synchronization: The GPIO class extension will synchronize this call 1573 | against other query/clear active and enabled interrupts. 1574 | Memory-mapped GPIO controllers: 1575 | Callbacks invoked at PASSIVE_LEVEL IRQL (e.g. interrupt 1576 | enable/disable/unmask or IO operations) may be active. Those 1577 | routines should acquire the interrupt lock prior to manipulating 1578 | any state accessed from within this routine. 1579 | 1580 | Serial-accessible GPIO controllers: 1581 | This call is synchronized with all other interrupt and IO callbacks. 1582 | 1583 | --*/ 1584 | 1585 | { 1586 | 1587 | PSIM_GPIO_BANK GpioBank; 1588 | PSIM_GPIO_CONTEXT GpioContext; 1589 | ULONG PinValue; 1590 | PSIM_GPIO_REGISTERS QcGpioRegisters; 1591 | 1592 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 1593 | GpioBank = &GpioContext->Banks[UnmaskParameters->BankId]; 1594 | QcGpioRegisters = GpioBank->Registers; 1595 | 1596 | // 1597 | // Unmask is same as enable on this GPIO controller. The difference between 1598 | // this routine and the enable routine is that unmask callback is called at 1599 | // DIRQL and automatically synchronized with other DIRQL-level callbacks. 1600 | // 1601 | 1602 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->EnableRegister); 1603 | PinValue |= (1 << UnmaskParameters->PinNumber); 1604 | WRITE_REGISTER_ULONG(&QcGpioRegisters->EnableRegister, PinValue); 1605 | 1606 | return STATUS_SUCCESS; 1607 | } 1608 | 1609 | _Must_inspect_result_ 1610 | _IRQL_requires_same_ 1611 | NTSTATUS 1612 | QcGpioQueryActiveInterrupts ( 1613 | _In_ PVOID Context, 1614 | _In_ PGPIO_QUERY_ACTIVE_INTERRUPTS_PARAMETERS QueryActiveParameters 1615 | ) 1616 | 1617 | /*++ 1618 | 1619 | Routine Description: 1620 | 1621 | This routine returns the current set of active interrupts. 1622 | 1623 | Arguments: 1624 | 1625 | Context - Supplies a pointer to the GPIO client driver's device extension. 1626 | 1627 | QueryActiveParameters - Supplies a pointer to a structure containing query 1628 | parameters. Fields are: 1629 | 1630 | BankId - Supplies the ID for the GPIO bank. 1631 | 1632 | EnabledMask - Supplies a bitmask of pins enabled for interrupts 1633 | on the specified GPIO bank. 1634 | 1635 | ActiveMask - Supplies a bitmask that receives the active interrupt 1636 | mask. If a pin is interrupting and set in EnabledMask, then the 1637 | corresponding bit is set in the bitmask. 1638 | 1639 | Return Value: 1640 | 1641 | NTSTATUS code (STATUS_SUCCESS always for memory-mapped GPIO controllers). 1642 | 1643 | Environment: 1644 | 1645 | Entry IRQL: DIRQL if the GPIO controller is memory-mapped; PASSIVE_LEVEL 1646 | if the controller is behind some serial-bus. 1647 | 1648 | N.B. For memory-mapped controllers, this routine is called from within 1649 | the interrupt context with the interrupt lock acquired by the class 1650 | extension. 1651 | 1652 | Synchronization: The GPIO class extension will synchronize this call 1653 | against other query/clear active and enabled interrupts. 1654 | Memory-mapped GPIO controllers: 1655 | Callbacks invoked at PASSIVE_LEVEL IRQL (e.g. interrupt 1656 | enable/disable/unmask or IO operations) may be active. Those 1657 | routines should acquire the interrupt lock prior to manipulating 1658 | any state accessed from within this routine. 1659 | 1660 | Serial-accessible GPIO controllers: 1661 | This call is synchronized with all other interrupt and IO callbacks. 1662 | 1663 | --*/ 1664 | 1665 | { 1666 | 1667 | PSIM_GPIO_BANK GpioBank; 1668 | PSIM_GPIO_CONTEXT GpioContext; 1669 | ULONG PinValue; 1670 | PSIM_GPIO_REGISTERS QcGpioRegisters; 1671 | 1672 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 1673 | GpioBank = &GpioContext->Banks[QueryActiveParameters->BankId]; 1674 | QcGpioRegisters = GpioBank->Registers; 1675 | 1676 | // 1677 | // NOTE: As QcGPIO is not a real hardware device, no interrupt will ever 1678 | // fire. Thus the status register value will never change. To pretend 1679 | // as if a real interrupt happened, it marks all currently enabled 1680 | // interrupts as asserting. Copy the enable interrupt value into 1681 | // the status register. 1682 | // 1683 | // This should NOT be done for a real GPIO controller. 1684 | // 1685 | 1686 | // 1687 | // BEGIN: QCGPIO HACK. 1688 | // 1689 | 1690 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->EnableRegister); 1691 | WRITE_REGISTER_ULONG(&QcGpioRegisters->StatusRegister, PinValue); 1692 | 1693 | // 1694 | // END: QCGPIO HACK. 1695 | // 1696 | 1697 | // 1698 | // Return the current value of the interrupt status register into the 1699 | // ActiveMask parameter. 1700 | // 1701 | 1702 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->StatusRegister); 1703 | QueryActiveParameters->ActiveMask = (ULONG64)PinValue; 1704 | return STATUS_SUCCESS; 1705 | } 1706 | 1707 | _Must_inspect_result_ 1708 | _IRQL_requires_same_ 1709 | NTSTATUS 1710 | QcGpioQueryEnabledInterrupts ( 1711 | _In_ PVOID Context, 1712 | _In_ PGPIO_QUERY_ENABLED_INTERRUPTS_PARAMETERS QueryEnabledParameters 1713 | ) 1714 | 1715 | /*++ 1716 | 1717 | Routine Description: 1718 | 1719 | This routine returns the current set of enabled interrupts. 1720 | 1721 | Arguments: 1722 | 1723 | Context - Supplies a pointer to the GPIO client driver's device extension. 1724 | 1725 | QueryEnabledParameters - Supplies a pointer to a structure containing query 1726 | parameters. Fields are: 1727 | 1728 | BankId - Supplies the ID for the GPIO bank. 1729 | 1730 | EnabledMask - Supplies a bitmask that receives the enabled interrupt 1731 | mask. If a pin is enabled, then the corresponding bit is set in the 1732 | mask. 1733 | 1734 | Return Value: 1735 | 1736 | NTSTATUS code (STATUS_SUCCESS always for memory-mapped GPIO controllers). 1737 | 1738 | Environment: 1739 | 1740 | Entry IRQL: DIRQL if the GPIO controller is memory-mapped; PASSIVE_LEVEL 1741 | if the controller is behind some serial-bus. 1742 | 1743 | N.B. For memory-mapped controllers, this routine is called with the 1744 | interrupt lock acquired by the class extension, but not always 1745 | from within the interrupt context. 1746 | 1747 | Synchronization: The GPIO class extension will synchronize this call 1748 | against other query/clear active and enabled interrupts. 1749 | Memory-mapped GPIO controllers: 1750 | Callbacks invoked at PASSIVE_LEVEL IRQL (e.g. interrupt 1751 | enable/disable/unmask or IO operations) may be active. Those 1752 | routines should acquire the interrupt lock prior to manipulating 1753 | any state accessed from within this routine. 1754 | 1755 | Serial-accessible GPIO controllers: 1756 | This call is synchronized with all other interrupt and IO callbacks. 1757 | 1758 | --*/ 1759 | 1760 | { 1761 | 1762 | PSIM_GPIO_BANK GpioBank; 1763 | PSIM_GPIO_CONTEXT GpioContext; 1764 | ULONG PinValue; 1765 | PSIM_GPIO_REGISTERS QcGpioRegisters; 1766 | 1767 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 1768 | GpioBank = &GpioContext->Banks[QueryEnabledParameters->BankId]; 1769 | QcGpioRegisters = GpioBank->Registers; 1770 | 1771 | // 1772 | // Return the current value of the interrupt enable register into the 1773 | // EnabledMask parameter. It is strongly preferred that the true state of 1774 | // the hardware is returned, rather than a software-cached variable, since 1775 | // CLIENT_QueryEnabledInterrupts is used by the class extension to detect 1776 | // interrupt storms. 1777 | // 1778 | 1779 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->EnableRegister); 1780 | QueryEnabledParameters->EnabledMask = (ULONG64)PinValue; 1781 | return STATUS_SUCCESS; 1782 | } 1783 | 1784 | _Must_inspect_result_ 1785 | _IRQL_requires_same_ 1786 | NTSTATUS 1787 | QcGpioClearActiveInterrupts ( 1788 | _In_ PVOID Context, 1789 | _In_ PGPIO_CLEAR_ACTIVE_INTERRUPTS_PARAMETERS ClearParameters 1790 | ) 1791 | 1792 | /*++ 1793 | 1794 | Routine Description: 1795 | 1796 | This routine clears the GPIO controller's active set of interrupts. 1797 | 1798 | Arguments: 1799 | 1800 | Context - Supplies a pointer to the GPIO client driver's device extension. 1801 | 1802 | ClearParameters - Supplies a pointer to a structure containing clear 1803 | operation parameters. Fields are: 1804 | 1805 | BankId - Supplies the ID for the GPIO bank. 1806 | 1807 | ClearActiveMask - Supplies a mask of pins which should be marked as 1808 | inactive. If a pin should be cleared, then the corresponding bit is 1809 | set in the mask. 1810 | 1811 | FailedMask - Supplies a bitmask of pins that failed to be cleared. If 1812 | a pin could not be cleared, the bit should be set in this field. 1813 | 1814 | N.B. This should only be done if for non memory-mapped controllers. 1815 | Memory-mapped controllers are never expected to fail this 1816 | operation. 1817 | 1818 | Return Value: 1819 | 1820 | NTSTATUS code (STATUS_SUCCESS always for memory-mapped GPIO controllers). 1821 | 1822 | Environment: 1823 | 1824 | Entry IRQL: DIRQL if the GPIO controller is memory-mapped; PASSIVE_LEVEL 1825 | if the controller is behind some serial-bus. 1826 | 1827 | N.B. For memory-mapped controllers, this routine is called from within 1828 | the interrupt context with the interrupt lock acquired by the class 1829 | extension. 1830 | 1831 | Synchronization: The GPIO class extension will synchronize this call 1832 | against other query/clear active and enabled interrupts. 1833 | Memory-mapped GPIO controllers: 1834 | Callbacks invoked at PASSIVE_LEVEL IRQL (e.g. interrupt 1835 | enable/disable/unmask or IO operations) may be active. Those 1836 | routines should acquire the interrupt lock prior to manipulating 1837 | any state accessed from within this routine. 1838 | 1839 | Serial-accessible GPIO controllers: 1840 | This call is synchronized with all other interrupt and IO callbacks. 1841 | 1842 | --*/ 1843 | 1844 | { 1845 | 1846 | PSIM_GPIO_BANK GpioBank; 1847 | PSIM_GPIO_CONTEXT GpioContext; 1848 | ULONG PinValue; 1849 | PSIM_GPIO_REGISTERS QcGpioRegisters; 1850 | 1851 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 1852 | GpioBank = &GpioContext->Banks[ClearParameters->BankId]; 1853 | QcGpioRegisters = GpioBank->Registers; 1854 | 1855 | // 1856 | // Clear the bits that are set in the ClearActiveMask parameter. 1857 | // 1858 | 1859 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->StatusRegister); 1860 | PinValue &= ~((ULONG)ClearParameters->ClearActiveMask); 1861 | WRITE_REGISTER_ULONG(&QcGpioRegisters->StatusRegister, PinValue); 1862 | 1863 | // 1864 | // Set the bitmask of pins that could not be successfully cleared. 1865 | // Since this is a memory-mapped controller, the clear operation always 1866 | // succeeds. 1867 | // 1868 | 1869 | ClearParameters->FailedClearMask = 0x0; 1870 | return STATUS_SUCCESS; 1871 | } 1872 | 1873 | NTSTATUS 1874 | QcGpioReconfigureInterrupt ( 1875 | _In_ PVOID Context, 1876 | _In_ PGPIO_RECONFIGURE_INTERRUPTS_PARAMETERS ReconfigureParameters 1877 | ) 1878 | 1879 | /*++ 1880 | 1881 | Routine Description: 1882 | 1883 | This routine reconfigures the interrupt in the specified mode. 1884 | 1885 | N.B. This routine is called with the interrupt lock acquired by the 1886 | class extension. Hence the lock is not re-acquired here. 1887 | 1888 | Arguments: 1889 | 1890 | Context - Supplies a pointer to the GPIO client driver's device extension. 1891 | 1892 | ReconfigureParameters - Supplies a pointer to a structure containing 1893 | parameters for reconfiguring the interrupt. Fields are: 1894 | 1895 | BankId - Supplies the ID for the GPIO bank. 1896 | 1897 | PinNumber - Supplies the interrupt line that should be reconfigured. 1898 | The pin number is relative to the bank. 1899 | 1900 | InterruptMode - Supplies the trigger mode (edge or level) for the new 1901 | configuration. 1902 | 1903 | Polarity - Supplies the polarity (active low or active high) for the 1904 | new configuration. 1905 | Note: For edge-triggered interrupts, ActiveLow corresponds to the 1906 | falling edge; ActiveHigh corresponds to the rising edge. 1907 | 1908 | Return Value: 1909 | 1910 | NTSTATUS code. 1911 | 1912 | Environment: 1913 | 1914 | Entry IRQL: DIRQL if the GPIO controller is memory-mapped; PASSIVE_LEVEL 1915 | if the controller is behind some serial-bus. 1916 | 1917 | N.B. For memory-mapped controllers, this routine is called from within 1918 | the interrupt context with the interrupt lock acquired by the class 1919 | extension. Hence the lock is not re-acquired here. 1920 | 1921 | Synchronization: The GPIO class extension will synchronize this call 1922 | against other query/clear active and enabled interrupts. 1923 | Memory-mapped GPIO controllers: 1924 | Callbacks invoked at PASSIVE_LEVEL IRQL (e.g. interrupt 1925 | enable/disable/unmask or IO operations) may be active. Those 1926 | routines should acquire the interrupt lock prior to manipulating 1927 | any state accessed from within this routine. 1928 | 1929 | Serial-accessible GPIO controllers: 1930 | This call is synchronized with all other interrupt and IO callbacks. 1931 | 1932 | --*/ 1933 | 1934 | { 1935 | 1936 | BANK_ID BankId; 1937 | PSIM_GPIO_BANK GpioBank; 1938 | PSIM_GPIO_CONTEXT GpioContext; 1939 | ULONG Index; 1940 | PIN_NUMBER PinNumber; 1941 | ULONG PinValue; 1942 | PIN_NUMBER ShiftBits; 1943 | PSIM_GPIO_REGISTERS QcGpioRegisters; 1944 | NTSTATUS Status; 1945 | 1946 | BankId = ReconfigureParameters->BankId; 1947 | PinNumber = ReconfigureParameters->PinNumber; 1948 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 1949 | GpioBank = &GpioContext->Banks[BankId]; 1950 | QcGpioRegisters = GpioBank->Registers; 1951 | Status = STATUS_SUCCESS; 1952 | 1953 | // 1954 | // Clear any stale status bits from the previous configuration. 1955 | // 1956 | 1957 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->StatusRegister); 1958 | PinValue &= ~(1 << PinNumber); 1959 | WRITE_REGISTER_ULONG(&QcGpioRegisters->StatusRegister, PinValue); 1960 | 1961 | // 1962 | // Set the mode register. If the interrupt is Level then set the bit; 1963 | // otherwise, clear it (edge-triggered). 1964 | // 1965 | 1966 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->ModeRegister); 1967 | if (ReconfigureParameters->InterruptMode == LevelSensitive) { 1968 | PinValue |= (1 << PinNumber); 1969 | } else { 1970 | PinValue &= ~(1 << PinNumber); 1971 | } 1972 | 1973 | WRITE_REGISTER_ULONG(&QcGpioRegisters->ModeRegister, PinValue); 1974 | 1975 | // 1976 | // Set the polarity register. There are two bits for each pin. If the 1977 | // interrupt is ActiveHigh (or Rising-edge) then set it to 0x1. 1978 | // 1979 | 1980 | Index = PinNumber / 16; 1981 | ShiftBits = (PinNumber % 16) * 2; 1982 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->PolarityRegister[Index]); 1983 | switch (ReconfigureParameters->Polarity) { 1984 | 1985 | case InterruptActiveHigh: 1986 | PinValue &= ~(0x3 << ShiftBits); 1987 | PinValue |= (1 << ShiftBits); 1988 | break; 1989 | 1990 | case InterruptActiveLow: 1991 | PinValue &= ~(0x3 << ShiftBits); 1992 | break; 1993 | 1994 | default: 1995 | 1996 | NT_ASSERT(FALSE); 1997 | } 1998 | 1999 | WRITE_REGISTER_ULONG(&QcGpioRegisters->PolarityRegister[Index], PinValue); 2000 | return STATUS_SUCCESS; 2001 | } 2002 | 2003 | // 2004 | // --------------------------------------------------------------- I/O Handlers 2005 | // 2006 | 2007 | _Must_inspect_result_ 2008 | _IRQL_requires_(PASSIVE_LEVEL) 2009 | NTSTATUS 2010 | QcGpioConnectIoPins ( 2011 | _In_ PVOID Context, 2012 | _In_ PGPIO_CONNECT_IO_PINS_PARAMETERS ConnectParameters 2013 | ) 2014 | 2015 | /*++ 2016 | 2017 | Routine Description: 2018 | 2019 | This routine invokes connects the specified pins for IO. The pins can 2020 | be read from if connected for input, or written to if connected for 2021 | output. 2022 | 2023 | N.B. This routine is called at PASSIVE_LEVEL but is not marked as 2024 | PAGED_CODE as it could be executed late in the hibernate or 2025 | early in resume sequence (or the deep-idle sequence). 2026 | 2027 | Arguments: 2028 | 2029 | Context - Supplies a pointer to the GPIO client driver's device extension. 2030 | 2031 | ConnectParameters - Supplies a pointer to a structure supplying the 2032 | parameters for connecting the IO pins. Fields description: 2033 | 2034 | BankId - Supplies the ID for the GPIO bank. 2035 | 2036 | PinNumberTable - Supplies an array of pins to be connected for IO. The 2037 | pin numbers are 0-based and relative to the GPIO bank. 2038 | 2039 | PinCount - Supplies the number of pins in the pin number table. 2040 | 2041 | ConnectMode - Supplies the mode in which the pins should be configured 2042 | (viz. input or output). 2043 | 2044 | ConnectFlags - Supplies the flags controlling the IO setup. Currently 2045 | no flags are defined. 2046 | 2047 | PullConfiguration - Supplies the pin pull-up/pull-down configuration. 2048 | 2049 | DebouceTimeout - Supplies the debounce timeout to be applied. The 2050 | field is in 100th of milli-seconds (i.e., 5.84ms will be supplied 2051 | as 584). Default value is zero, which implies, no debounce. 2052 | 2053 | DriveStrength - Supplies the drive strength to be applied. The value 2054 | is in 100th of mA (i.e., 1.21mA will be supplied as 121mA). 2055 | 2056 | VendorData - Supplies an optional pointer to a buffer containing the 2057 | vendor data supplied in the GPIO descriptor. This field will be 2058 | NULL if no vendor data was supplied. This buffer is read-only. 2059 | 2060 | VendorDataLength - Supplies the length of the vendor data buffer. 2061 | 2062 | ConnectFlags - Supplies the flag to be used for connect operation. 2063 | Currently no flags are defined. 2064 | 2065 | Return Value: 2066 | 2067 | NT status code. 2068 | 2069 | Environment: 2070 | 2071 | Entry IRQL: PASSIVE_LEVEL. 2072 | 2073 | Synchronization: The GPIO class extension will synchronize this call 2074 | against other passive-level interrupt callbacks (e.g. enable/disable/ 2075 | unmask) and IO callbacks. 2076 | 2077 | --*/ 2078 | 2079 | { 2080 | 2081 | PSIM_GPIO_BANK GpioBank; 2082 | PSIM_GPIO_CONTEXT GpioContext; 2083 | ULONG Index; 2084 | PIN_NUMBER PinNumber; 2085 | PPIN_NUMBER PinNumberTable; 2086 | ULONG PinValue; 2087 | PSIM_GPIO_REGISTERS QcGpioRegisters; 2088 | NTSTATUS Status; 2089 | 2090 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 2091 | GpioBank = &GpioContext->Banks[ConnectParameters->BankId]; 2092 | QcGpioRegisters = GpioBank->Registers; 2093 | Status = STATUS_SUCCESS; 2094 | 2095 | // 2096 | // Read the current direction register value. 2097 | // 2098 | 2099 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->DirectionRegister); 2100 | 2101 | // 2102 | // Walk through all the supplied pins and connect them in the specified 2103 | // mode (input or output). 2104 | // 2105 | 2106 | PinNumberTable = ConnectParameters->PinNumberTable; 2107 | for (Index = 0; Index < ConnectParameters->PinCount; Index += 1) { 2108 | PinNumber = PinNumberTable[Index]; 2109 | 2110 | // 2111 | // If the pins are being connected for input, then set the bit. 2112 | // Otherwise clear the bit. 2113 | // 2114 | 2115 | if (ConnectParameters->ConnectMode == ConnectModeInput) { 2116 | PinValue |= (1 << PinNumber); 2117 | 2118 | } else if (ConnectParameters->ConnectMode == ConnectModeOutput) { 2119 | PinValue &= ~(1 << PinNumber); 2120 | } 2121 | } 2122 | 2123 | WRITE_REGISTER_ULONG(&QcGpioRegisters->DirectionRegister, PinValue); 2124 | return Status; 2125 | } 2126 | 2127 | _Must_inspect_result_ 2128 | _IRQL_requires_(PASSIVE_LEVEL) 2129 | NTSTATUS 2130 | QcGpioDisconnectIoPins ( 2131 | _In_ PVOID Context, 2132 | _In_ PGPIO_DISCONNECT_IO_PINS_PARAMETERS DisconnectParameters 2133 | ) 2134 | 2135 | /*++ 2136 | 2137 | Routine Description: 2138 | 2139 | This routine invokes disconnects the specified IO pins. The pins are 2140 | put back in their original mode. 2141 | 2142 | N.B. This routine is called at PASSIVE_LEVEL but is not marked as 2143 | PAGED_CODE as it could be executed late in the hibernate or 2144 | early in resume sequence (or the deep-idle sequence). 2145 | 2146 | Arguments: 2147 | 2148 | Context - Supplies a pointer to the GPIO client driver's device extension. 2149 | 2150 | DisconnectParameters - Supplies a pointer to a structure containing 2151 | disconnect operation parameters. Fields are: 2152 | 2153 | BankId - Supplies the ID for the GPIO bank. 2154 | 2155 | PinNumberTable - Supplies an array of pins to be disconnected. The pin 2156 | numbers are relative to the GPIO bank. 2157 | 2158 | PinCount - Supplies the number of pins in the pin number table. 2159 | 2160 | DisconnectMode - Supplies the mode in which the pins are currently 2161 | configured (viz. input or output). 2162 | 2163 | DisconnectFlags - Supplies the flags controlling the IO setup. Currently 2164 | no flags are defined. 2165 | 2166 | Return Value: 2167 | 2168 | NTSTATUS code (STATUS_SUCCESS always for memory-mapped GPIO controllers). 2169 | 2170 | Environment: 2171 | 2172 | Entry IRQL: PASSIVE_LEVEL. 2173 | 2174 | Synchronization: The GPIO class extension will synchronize this call 2175 | against other passive-level interrupt callbacks (e.g. enable/disable/ 2176 | unmask) and IO callbacks. 2177 | 2178 | --*/ 2179 | 2180 | { 2181 | 2182 | PSIM_GPIO_BANK GpioBank; 2183 | PSIM_GPIO_CONTEXT GpioContext; 2184 | ULONG Index; 2185 | PIN_NUMBER PinNumber; 2186 | PPIN_NUMBER PinNumberTable; 2187 | ULONG PinValue; 2188 | PSIM_GPIO_REGISTERS QcGpioRegisters; 2189 | 2190 | // 2191 | // If the pin configuration should be preserved post disconnect, then 2192 | // there is nothing left to do. 2193 | // 2194 | 2195 | if (DisconnectParameters->DisconnectFlags.PreserveConfiguration == 1) { 2196 | return STATUS_SUCCESS; 2197 | } 2198 | 2199 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 2200 | GpioBank = &GpioContext->Banks[DisconnectParameters->BankId]; 2201 | QcGpioRegisters = GpioBank->Registers; 2202 | 2203 | // 2204 | // Read the current direction register value. 2205 | // 2206 | 2207 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->DirectionRegister); 2208 | 2209 | // 2210 | // Walk through all the supplied pins and disconnect them. On QcGPIO 2211 | // controller, all pins are reset to the default mode (output). 2212 | // 2213 | 2214 | PinNumberTable = DisconnectParameters->PinNumberTable; 2215 | for (Index = 0; Index < DisconnectParameters->PinCount; Index += 1) { 2216 | PinNumber = PinNumberTable[Index]; 2217 | PinValue &= ~(1 << PinNumber); 2218 | } 2219 | 2220 | WRITE_REGISTER_ULONG(&QcGpioRegisters->DirectionRegister, PinValue); 2221 | 2222 | return STATUS_SUCCESS; 2223 | } 2224 | 2225 | _Must_inspect_result_ 2226 | NTSTATUS 2227 | QcGpioReadGpioPins ( 2228 | _In_ PVOID Context, 2229 | _In_ PGPIO_READ_PINS_MASK_PARAMETERS ReadParameters 2230 | ) 2231 | 2232 | /*++ 2233 | 2234 | Routine Description: 2235 | 2236 | This routine reads the current values for all the pins. 2237 | 2238 | As the FormatIoRequestsAsMasks bit was set inside 2239 | QcGpioQueryControllerInformation(), all this routine needs to do is read 2240 | the level register value and return to the GPIO class extension. It will 2241 | return the right set of bits to the caller. 2242 | 2243 | N.B. This routine is called at DIRQL for memory-mapped GPIOs and thus not 2244 | marked as PAGED. 2245 | 2246 | Arguments: 2247 | 2248 | Context - Supplies a pointer to the GPIO client driver's device extension. 2249 | 2250 | ReadParameters - Supplies a pointer to a structure containing read 2251 | operation parameters. Fields are: 2252 | 2253 | BankId - Supplies the ID for the GPIO bank. 2254 | 2255 | PinValues - Supplies a pointer to a variable that receives the current 2256 | pin values. 2257 | 2258 | Flags - Supplies the flag to be used for read operation. Currently 2259 | defined flags are: 2260 | 2261 | WriteConfiguredPins: If set, the read is being done on a set of 2262 | pin that were configured for write. In such cases, the 2263 | GPIO client driver is expected to read and return the 2264 | output register value. 2265 | 2266 | Return Value: 2267 | 2268 | NTSTATUS code (STATUS_SUCCESS always for memory-mapped GPIO controllers). 2269 | 2270 | Environment: 2271 | 2272 | Entry IRQL: DIRQL if the GPIO controller is memory-mapped; 2273 | PASSIVE_LEVEL if the controller is behind some serial-bus. 2274 | 2275 | Synchronization: The GPIO class extension will synchronize this call 2276 | against other passive-level interrupt callbacks (e.g. enable/disable) 2277 | and IO callbacks (connect/disconnect). 2278 | 2279 | --*/ 2280 | 2281 | { 2282 | 2283 | PSIM_GPIO_BANK GpioBank; 2284 | PSIM_GPIO_CONTEXT GpioContext; 2285 | ULONG PinValue; 2286 | PSIM_GPIO_REGISTERS QcGpioRegisters; 2287 | 2288 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 2289 | GpioBank = &GpioContext->Banks[ReadParameters->BankId]; 2290 | QcGpioRegisters = GpioBank->Registers; 2291 | 2292 | // 2293 | // Read the current level register value. Note the GPIO class may invoke 2294 | // the read routine on write-configured pins. In such case the output 2295 | // register values should be read. 2296 | // 2297 | // N.B. In case of QcGPIO, the LevelRegister holds the value for input 2298 | // as well as output pins. Thus the same register is read in either 2299 | // case. 2300 | // 2301 | 2302 | if (ReadParameters->Flags.WriteConfiguredPins == FALSE) { 2303 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->LevelRegister); 2304 | 2305 | } else { 2306 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->LevelRegister); 2307 | } 2308 | 2309 | *ReadParameters->PinValues = PinValue; 2310 | return STATUS_SUCCESS; 2311 | } 2312 | 2313 | _Must_inspect_result_ 2314 | NTSTATUS 2315 | QcGpioWriteGpioPins ( 2316 | _In_ PVOID Context, 2317 | _In_ PGPIO_WRITE_PINS_MASK_PARAMETERS WriteParameters 2318 | ) 2319 | 2320 | /*++ 2321 | 2322 | Routine Description: 2323 | 2324 | This routine sets the current values for the specified pins. This call is 2325 | synchronized with the write and connect/disconnect IO calls. 2326 | 2327 | N.B. This routine is called at DIRQL for memory-mapped GPIOs and thus not 2328 | marked as PAGED. 2329 | 2330 | Arguments: 2331 | 2332 | Context - Supplies a pointer to the GPIO client driver's device extension. 2333 | 2334 | WriteParameters - Supplies a pointer to a structure containing write 2335 | operation parameters. Fields are: 2336 | 2337 | BankId - Supplies the ID for the GPIO bank. 2338 | 2339 | SetMask - Supplies a mask of pins which should be set (0x1). If a pin 2340 | should be set, then the corresponding bit is set in the mask. 2341 | All bits that are clear in the mask should be left intact. 2342 | 2343 | ClearMask - Supplies a mask of pins which should be cleared (0x0). If 2344 | a pin should be cleared, then the bit is set in the bitmask. All 2345 | bits that are clear in the mask should be left intact. 2346 | 2347 | Flags - Supplies the flag controlling the write operation. Currently 2348 | no flags are defined. 2349 | 2350 | Return Value: 2351 | 2352 | NTSTATUS code (STATUS_SUCCESS always for memory-mapped GPIO controllers). 2353 | 2354 | Environment: 2355 | 2356 | Entry IRQL: DIRQL if the GPIO controller is memory-mapped; 2357 | PASSIVE_LEVEL if the controller is behind some serial-bus. 2358 | 2359 | Synchronization: The GPIO class extension will synchronize this call 2360 | against other passive-level interrupt callbacks (e.g. enable/disable) 2361 | and IO callbacks (connect/disconnect). 2362 | 2363 | --*/ 2364 | 2365 | { 2366 | 2367 | PSIM_GPIO_BANK GpioBank; 2368 | PSIM_GPIO_CONTEXT GpioContext; 2369 | ULONG PinValue; 2370 | PSIM_GPIO_REGISTERS QcGpioRegisters; 2371 | 2372 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 2373 | GpioBank = &GpioContext->Banks[WriteParameters->BankId]; 2374 | QcGpioRegisters = GpioBank->Registers; 2375 | 2376 | // 2377 | // Read the current level register value. 2378 | // 2379 | 2380 | PinValue = READ_REGISTER_ULONG(&QcGpioRegisters->LevelRegister); 2381 | 2382 | // 2383 | // Set the bits specified in the set mask and clear the ones specified 2384 | // in the clear mask. 2385 | // 2386 | 2387 | PinValue |= WriteParameters->SetMask; 2388 | PinValue &= ~WriteParameters->ClearMask; 2389 | 2390 | // 2391 | // Write the updated value to the register. 2392 | // 2393 | 2394 | WRITE_REGISTER_ULONG(&QcGpioRegisters->LevelRegister, PinValue); 2395 | 2396 | return STATUS_SUCCESS; 2397 | } 2398 | 2399 | // 2400 | // ------------------------------------------------------- Power mgmt handlers 2401 | // 2402 | 2403 | VOID 2404 | QcGpioSaveBankHardwareContext ( 2405 | _In_ PVOID Context, 2406 | _In_ PGPIO_SAVE_RESTORE_BANK_HARDWARE_CONTEXT_PARAMETERS SaveParameters 2407 | ) 2408 | 2409 | /*++ 2410 | 2411 | Routine Description: 2412 | 2413 | This routine saves the hardware context for the GPIO controller. 2414 | 2415 | Arguments: 2416 | 2417 | Context - Supplies a pointer to the GPIO client driver's device extension. 2418 | 2419 | SaveRestoreParameters - Supplies a pointer to a structure containing 2420 | parameters for the save operation: 2421 | 2422 | BankId - Supplies the ID for the GPIO bank. 2423 | 2424 | State - Target F-state the bank will be transitioned into. 2425 | 2426 | Flags - Supplies flags for the save operation: 2427 | CriticalTransition - TRUE if this is due to a critical transition. 2428 | 2429 | Return Value: 2430 | 2431 | None. 2432 | 2433 | --*/ 2434 | 2435 | { 2436 | 2437 | PULONG DestinationAddress; 2438 | PSIM_GPIO_BANK GpioBank; 2439 | PSIM_GPIO_CONTEXT GpioContext; 2440 | ULONG Index; 2441 | ULONG RegisterCount; 2442 | PSIM_GPIO_REGISTERS QcGpioRegisters; 2443 | PULONG SourceAddress; 2444 | 2445 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 2446 | GpioBank = &GpioContext->Banks[SaveParameters->BankId]; 2447 | QcGpioRegisters = GpioBank->Registers; 2448 | 2449 | // 2450 | // Copy the contents of the registers into memory. 2451 | // 2452 | 2453 | SourceAddress = &QcGpioRegisters->ModeRegister; 2454 | DestinationAddress = &GpioBank->SavedContext.ModeRegister; 2455 | RegisterCount = sizeof(SIM_GPIO_REGISTERS) / sizeof(ULONG); 2456 | for (Index = 0; Index < RegisterCount; Index += 1) { 2457 | *DestinationAddress = READ_REGISTER_ULONG(SourceAddress); 2458 | SourceAddress += 1; 2459 | DestinationAddress += 1; 2460 | } 2461 | 2462 | return; 2463 | } 2464 | 2465 | VOID 2466 | QcGpioRestoreBankHardwareContext ( 2467 | _In_ PVOID Context, 2468 | _In_ PGPIO_SAVE_RESTORE_BANK_HARDWARE_CONTEXT_PARAMETERS RestoreParameters 2469 | ) 2470 | 2471 | /*++ 2472 | 2473 | Routine Description: 2474 | 2475 | This routine saves the hardware context for the GPIO controller. 2476 | 2477 | Arguments: 2478 | 2479 | Context - Supplies a pointer to the GPIO client driver's device extension. 2480 | 2481 | SaveRestoreParameters - Supplies a pointer to a structure containing 2482 | parameters for the restore operation: 2483 | 2484 | BankId - Supplies the ID for the GPIO bank. 2485 | 2486 | State - Target F-state the bank will be transitioned into. 2487 | 2488 | Flags - Supplies flags for the save operation: 2489 | CriticalTransition - TRUE if this is due to a critical transition. 2490 | 2491 | Return Value: 2492 | 2493 | None. 2494 | 2495 | --*/ 2496 | 2497 | { 2498 | 2499 | PSIM_GPIO_BANK GpioBank; 2500 | PSIM_GPIO_CONTEXT GpioContext; 2501 | ULONG PinValue; 2502 | PSIM_GPIO_REGISTERS QcGpioRegisters; 2503 | 2504 | GpioContext = (PSIM_GPIO_CONTEXT)Context; 2505 | GpioBank = &GpioContext->Banks[RestoreParameters->BankId]; 2506 | QcGpioRegisters = GpioBank->Registers; 2507 | 2508 | // 2509 | // Restore the level register. 2510 | // 2511 | 2512 | PinValue = GpioBank->SavedContext.LevelRegister; 2513 | WRITE_REGISTER_ULONG(&QcGpioRegisters->LevelRegister, PinValue); 2514 | 2515 | // 2516 | // Restore the mode, polarity and enable registers. 2517 | // 2518 | 2519 | PinValue = GpioBank->SavedContext.ModeRegister; 2520 | WRITE_REGISTER_ULONG(&QcGpioRegisters->ModeRegister, PinValue); 2521 | 2522 | PinValue = GpioBank->SavedContext.PolarityRegister[0]; 2523 | WRITE_REGISTER_ULONG(&QcGpioRegisters->PolarityRegister[0], PinValue); 2524 | 2525 | PinValue = GpioBank->SavedContext.PolarityRegister[1]; 2526 | WRITE_REGISTER_ULONG(&QcGpioRegisters->PolarityRegister[1], PinValue); 2527 | 2528 | PinValue = GpioBank->SavedContext.StatusRegister; 2529 | WRITE_REGISTER_ULONG(&QcGpioRegisters->StatusRegister, PinValue); 2530 | 2531 | // 2532 | // Restore the direction register. 2533 | // 2534 | 2535 | PinValue = GpioBank->SavedContext.DirectionRegister; 2536 | WRITE_REGISTER_ULONG(&QcGpioRegisters->DirectionRegister, PinValue); 2537 | 2538 | // 2539 | // Take care to restore the enable register only after restoring the 2540 | // mode and polarity registers. Otherwise, the interrupt line will get 2541 | // sampled when the enable register gets written to with the mode and 2542 | // polarity at that point in time (and could cause a spurious interrupt). 2543 | // 2544 | 2545 | PinValue = GpioBank->SavedContext.EnableRegister; 2546 | WRITE_REGISTER_ULONG(&QcGpioRegisters->EnableRegister, PinValue); 2547 | 2548 | return; 2549 | } 2550 | 2551 | __pragma(warning(default: 4127)) // conditional expression is a constant 2552 | 2553 | 2554 | -------------------------------------------------------------------------------- /buses/gpio/qcgpio.inx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WOA-Project/Project-Croissant/396017fcec81105165e66cbb74eb4672c4bbdbcc/buses/gpio/qcgpio.inx -------------------------------------------------------------------------------- /buses/gpio/qcgpio.rc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #define VER_FILETYPE VFT_DLL 6 | #define VER_FILESUBTYPE VFT2_UNKNOWN 7 | #define VER_FILEDESCRIPTION_STR "Simulated GPIO Client" 8 | #define VER_INTERNALNAME_STR "simgpio.sys" 9 | #define VER_ORIGINALFILENAME_STR "simgpio.sys" 10 | 11 | #include "common.ver" 12 | 13 | -------------------------------------------------------------------------------- /buses/gpio/qcgpio.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | ARM64 7 | 8 | 9 | Release 10 | ARM64 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {A80FE9DD-C140-40F6-A3F4-55A2A55BFAD4} 23 | $(MSBuildProjectName) 24 | 1 25 | Debug 26 | x64 27 | {157FF815-CA85-49A2-B622-5D57EFAB0A13} 28 | $(LatestTargetPlatformVersion) 29 | 30 | 31 | 32 | Windows10 33 | False 34 | Universal 35 | KMDF 36 | WindowsKernelModeDriver10.0 37 | Driver 38 | 39 | 40 | Windows10 41 | False 42 | Universal 43 | KMDF 44 | WindowsKernelModeDriver10.0 45 | Driver 46 | 47 | 48 | Windows10 49 | True 50 | Universal 51 | KMDF 52 | WindowsKernelModeDriver10.0 53 | Driver 54 | 55 | 56 | Windows10 57 | True 58 | Universal 59 | KMDF 60 | WindowsKernelModeDriver10.0 61 | Driver 62 | 63 | 64 | 65 | $(IntDir) 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | * 82 | true 83 | $(InfArch) 84 | true 85 | .\$(IntDir)\qcgpio.inf 86 | 87 | 88 | 89 | qcgpio 90 | 91 | 92 | qcgpio 93 | 94 | 95 | qcgpio 96 | 97 | 98 | qcgpio 99 | 100 | 101 | 102 | %(AdditionalDependencies);$(DDK_LIB_PATH)\ksguid.lib;$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\msgpioclxstub.lib 103 | 104 | 105 | true 106 | Level4 107 | 108 | 109 | 110 | 111 | sha256 112 | 113 | 114 | 115 | 116 | %(AdditionalDependencies);$(DDK_LIB_PATH)\ksguid.lib;$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\msgpioclxstub.lib 117 | 118 | 119 | true 120 | Level4 121 | 122 | 123 | 124 | 125 | sha256 126 | 127 | 128 | 129 | 130 | %(AdditionalDependencies);$(DDK_LIB_PATH)\ksguid.lib;$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\msgpioclxstub.lib 131 | 132 | 133 | true 134 | Level4 135 | 136 | 137 | 138 | 139 | sha256 140 | 141 | 142 | 143 | 144 | %(AdditionalDependencies);$(DDK_LIB_PATH)\ksguid.lib;$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\msgpioclxstub.lib 145 | 146 | 147 | true 148 | Level4 149 | 150 | 151 | 152 | 153 | sha256 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /buses/gpio/qcgpio.vcxproj.Filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* 6 | {E10CB9FB-4852-4353-85F5-667D4D2A13DD} 7 | 8 | 9 | h;hpp;hxx;hm;inl;inc;xsd 10 | {EC8940D8-5E2B-49AB-AB85-7CABCAE698D1} 11 | 12 | 13 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml 14 | {42A1FDF4-6DB4-41B2-9423-8002A20D1B0D} 15 | 16 | 17 | inf;inv;inx;mof;mc; 18 | {FD9F921C-D1EF-421B-A692-F23423B32E64} 19 | 20 | 21 | 22 | 23 | Driver Files 24 | 25 | 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Resource Files 34 | 35 | 36 | -------------------------------------------------------------------------------- /hals/halext/HalExtQcHypGic3IrmSupport.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.11.35111.106 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HalExtQcHypGic3IrmSupport", "HalExtQcHypGic3IrmSupport\HalExtQcHypGic3IrmSupport.vcxproj", "{708FC03F-4440-4AF4-B68F-5ADE99A0690B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM64 = Debug|ARM64 11 | Release|ARM64 = Release|ARM64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {708FC03F-4440-4AF4-B68F-5ADE99A0690B}.Debug|ARM64.ActiveCfg = Debug|ARM64 15 | {708FC03F-4440-4AF4-B68F-5ADE99A0690B}.Debug|ARM64.Build.0 = Debug|ARM64 16 | {708FC03F-4440-4AF4-B68F-5ADE99A0690B}.Release|ARM64.ActiveCfg = Release|ARM64 17 | {708FC03F-4440-4AF4-B68F-5ADE99A0690B}.Release|ARM64.Build.0 = Release|ARM64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {1A8EB14F-CB71-40EC-89E9-884C429D719C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /hals/halext/HalExtQcHypGic3IrmSupport/HalExtQcHypGic3IrmSupport.c: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) 2024 The DuoWoA authors 4 | 5 | Module Name: 6 | 7 | HalExtQcHypGic3IrmSupport.c 8 | 9 | Abstract: 10 | 11 | This file implements a HAL Extension Module for 12 | Qualcomm Hypervisor Missing GicV3 IRM Bit Support. 13 | 14 | Author: 15 | 16 | Gustave Monce (gmonce) 8-23-2024 17 | 18 | --*/ 19 | 20 | // 21 | // ------------------------------------------------------------------- Includes 22 | // 23 | 24 | #include 25 | #include 26 | 27 | // 28 | // ---------------------------------------------------------------- Definitions 29 | // 30 | 31 | #define VBAR_EL1_SYSREG ARM64_SYSREG(3, 0, 12, 0, 0) 32 | 33 | // 34 | // ------------------------------------------------- Data Structure Definitions 35 | // 36 | 37 | // 38 | // ----------------------------------------------- Internal Function Prototypes 39 | // 40 | 41 | // 42 | // ------------------------------------------------------------------ Functions 43 | // 44 | 45 | NTSTATUS 46 | AddResourceGroup ( 47 | __in ULONG Handle, 48 | __in PCSRT_RESOURCE_GROUP_HEADER ResourceGroup 49 | ) 50 | 51 | /*++ 52 | 53 | Routine Description: 54 | 55 | This routine patches the main kernel HAL code to work without the IRM Bit. 56 | 57 | Arguments: 58 | 59 | Handle - Supplies the HAL Extension handle which must be passed to other 60 | HAL Extension APIs. 61 | 62 | ResourceGroup - Supplies a pointer to the Resource Group which the 63 | HAL Extension has been installed on. 64 | 65 | Return Value: 66 | 67 | NTSTATUS code. 68 | 69 | --*/ 70 | 71 | { 72 | UNREFERENCED_PARAMETER(Handle); 73 | UNREFERENCED_PARAMETER(ResourceGroup); 74 | 75 | // VBAR_EL1 always points to KiArm64ExceptionVectors on Windows 76 | UINT64 VBAR_EL1 = _ReadStatusReg(VBAR_EL1_SYSREG); 77 | 78 | // Try to find the base of the kernel now 79 | UINT64 KernelBase = VBAR_EL1; 80 | while (TRUE) 81 | { 82 | if (*((PUINT16)KernelBase) == 0x5A4D) // MZ 83 | { 84 | // We found the base of the kernel image. 85 | break; 86 | } 87 | 88 | KernelBase--; 89 | } 90 | 91 | // Now that we have the base of the kernel, scan the entire file for 92 | // the problematic instruction 93 | 94 | // TODO: Get Kernel Size? 95 | UINT64 GICINSTR = 0; 96 | UINT64 current = KernelBase; 97 | while (TRUE) 98 | { 99 | if (*(UINT32 *)current == 0xD518CBA8) // msr icc_sgi1r_el1, x8 100 | { 101 | GICINSTR = current; 102 | break; 103 | } 104 | 105 | if (*(UINT32 *)current == 0xD518CBAA) // msr icc_sgi1r_el1, x10 106 | { 107 | GICINSTR = current; 108 | break; 109 | } 110 | 111 | current += sizeof(UINT32); 112 | } 113 | 114 | // We now have the address of the msr icc_sgi1r_el1, xXX instruction 115 | // We now inject our code 116 | 117 | // TODO 118 | 119 | // We always return success as we are not a real hal extension. 120 | return STATUS_SUCCESS; 121 | } 122 | -------------------------------------------------------------------------------- /hals/halext/HalExtQcHypGic3IrmSupport/HalExtQcHypGic3IrmSupport.def: -------------------------------------------------------------------------------- 1 | LIBRARY HalExtQcHypGic3IrmSupport 2 | 3 | -------------------------------------------------------------------------------- /hals/halext/HalExtQcHypGic3IrmSupport/HalExtQcHypGic3IrmSupport.inx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WOA-Project/Project-Croissant/396017fcec81105165e66cbb74eb4672c4bbdbcc/hals/halext/HalExtQcHypGic3IrmSupport/HalExtQcHypGic3IrmSupport.inx -------------------------------------------------------------------------------- /hals/halext/HalExtQcHypGic3IrmSupport/HalExtQcHypGic3IrmSupport.rc: -------------------------------------------------------------------------------- 1 | #include "verrsrc.h" 2 | #include 3 | 4 | #define VER_FILETYPE VFT_DLL 5 | #define VER_FILESUBTYPE VFT_UNKNOWN 6 | #define VER_FILEDESCRIPTION_STR "Qualcomm(R) Hypervisor GICv3 IRM Support HAL Extension" 7 | #define VER_INTERNALNAME_STR "HalExtQcHypGic3IrmSupport.DLL" 8 | #define VER_ORIGINALFILENAME_STR "HalExtQcHypGic3IrmSupport.DLL" 9 | 10 | #include 11 | -------------------------------------------------------------------------------- /hals/halext/HalExtQcHypGic3IrmSupport/HalExtQcHypGic3IrmSupport.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | ARM64 7 | 8 | 9 | Release 10 | ARM64 11 | 12 | 13 | 14 | {708FC03F-4440-4AF4-B68F-5ADE99A0690B} 15 | $(MSBuildProjectName) 16 | 1 17 | Debug 18 | ARM64 19 | {74DA088F-D0F8-4839-9BFF-3C72F7D46E64} 20 | 10.0.26100.0 21 | 22 | 23 | 24 | Windows10 25 | False 26 | Universal 27 | 28 | WindowsApplicationForDrivers10.0 29 | DynamicLibrary 30 | 31 | 32 | Windows10 33 | True 34 | Universal 35 | 36 | WindowsApplicationForDrivers10.0 37 | DynamicLibrary 38 | 39 | 40 | 41 | $(IntDir) 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | HalExtensionInit@12 53 | HalExtensionInit 54 | 55 | 56 | 57 | 58 | HalExtensionInit@12 59 | HalExtensionInit 60 | 61 | 62 | 63 | HalExtQcHypGic3IrmSupport 64 | 65 | 66 | HalExtQcHypGic3IrmSupport 67 | 68 | 69 | 70 | %(AdditionalIncludeDirectories);$(DDK_INC_PATH) 71 | 72 | 73 | %(AdditionalIncludeDirectories);$(DDK_INC_PATH) 74 | true 75 | Level4 76 | %(AdditionalOptions) /J 77 | 78 | 79 | 80 | 81 | %(AdditionalIncludeDirectories);$(DDK_INC_PATH) 82 | 83 | 84 | %(AdditionalDependencies);$(DDK_LIB_PATH)halextlib.lib;$(DDK_LIB_PATH)libcntpr.lib;$(DDK_LIB_PATH)bufferoverflowfastfailk.lib 85 | %(AdditionalOptions) -merge:PAGECONST=PAGE -merge:INITCONST=INIT /LARGEADDRESSAWARE 86 | HalExtQcHypGic3IrmSupport.def 87 | 88 | 89 | 90 | 91 | %(AdditionalIncludeDirectories);$(DDK_INC_PATH) 92 | 93 | 94 | %(AdditionalIncludeDirectories);$(DDK_INC_PATH) 95 | true 96 | Level4 97 | %(AdditionalOptions) /J 98 | 99 | 100 | 101 | 102 | %(AdditionalIncludeDirectories);$(DDK_INC_PATH) 103 | 104 | 105 | %(AdditionalDependencies);$(DDK_LIB_PATH)halextlib.lib;$(DDK_LIB_PATH)libcntpr.lib;$(DDK_LIB_PATH)bufferoverflowfastfailk.lib 106 | %(AdditionalOptions) -merge:PAGECONST=PAGE -merge:INITCONST=INIT /LARGEADDRESSAWARE 107 | HalExtQcHypGic3IrmSupport.def 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | $(OutDir)\HalExtQcHypGic3IrmSupport.inf 117 | * 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /hals/halext/HalExtQcHypGic3IrmSupport/HalExtQcHypGic3IrmSupport.vcxproj.Filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* 6 | {5E4E1ADC-DD92-4AFF-B021-09A73A1D08DF} 7 | 8 | 9 | h;hpp;hxx;hm;inl;inc;xsd 10 | {E29262B9-C497-404D-A5E0-5E6064005E48} 11 | 12 | 13 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml 14 | {E3A98D78-1B54-4D53-AFC0-D44C9D37EC38} 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | 28 | 29 | Source Files 30 | 31 | 32 | --------------------------------------------------------------------------------