00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "iop.h"
00022
#pragma hdrstop
00023
00024 #define BUGFEST_HACKS
00025
00026
00027
00028
00029
00030 #define MAX_ULONGLONG ((ULONGLONG) -1)
00031 #define MAX_ALIAS_PORT 0x0000FFFF
00032
00033 typedef struct _PORT_ARBITER_EXTENSION {
00034
00035 PRTL_RANGE_LIST
Aliases;
00036 PRTL_RANGE_LIST
PossibleAliases;
00037 RTL_RANGE_LIST
RangeLists[2];
00038
00039 }
PORT_ARBITER_EXTENSION, *
PPORT_ARBITER_EXTENSION;
00040
00041
00042
00043
00044
00045
VOID
00046
IopPortBacktrackAllocation(
00047 IN PARBITER_INSTANCE Arbiter,
00048 IN
PARBITER_ALLOCATION_STATE State
00049 );
00050
00051 BOOLEAN
00052
IopPortGetNextAlias(
00053 ULONG IoDescriptorFlags,
00054 ULONGLONG LastAlias,
00055 PULONGLONG NextAlias
00056 );
00057
00058 BOOLEAN
00059
IopPortFindSuitableRange(
00060 PARBITER_INSTANCE Arbiter,
00061
PARBITER_ALLOCATION_STATE State
00062 );
00063
00064 BOOLEAN
00065
IopMemFindSuitableRange(
00066 PARBITER_INSTANCE Arbiter,
00067
PARBITER_ALLOCATION_STATE State
00068 );
00069
00070
00071
NTSTATUS
00072
IopGenericUnpackRequirement(
00073 IN PIO_RESOURCE_DESCRIPTOR Descriptor,
00074 OUT PULONGLONG Minimum,
00075 OUT PULONGLONG Maximum,
00076 OUT PULONG Length,
00077 OUT PULONG Alignment
00078 );
00079
00080
NTSTATUS
00081
IopGenericPackResource(
00082 IN PIO_RESOURCE_DESCRIPTOR Requirement,
00083 IN ULONGLONG Start,
00084 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
00085 );
00086
00087 LONG
00088
IopGenericScoreRequirement(
00089 IN PIO_RESOURCE_DESCRIPTOR Descriptor
00090 );
00091
00092
NTSTATUS
00093
IopGenericUnpackResource(
00094 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
00095 OUT PULONGLONG Start,
00096 OUT PULONG Length
00097 );
00098
00099 BOOLEAN
00100
IopPortIsAliasedRangeAvailable(
00101 IN PARBITER_INSTANCE Arbiter,
00102 IN
PARBITER_ALLOCATION_STATE State
00103 );
00104
00105
NTSTATUS
00106
IopMemInitialize(
00107 VOID
00108 );
00109
00110
VOID
00111
IopPortAddAllocation(
00112 IN PARBITER_INSTANCE Arbiter,
00113 IN
PARBITER_ALLOCATION_STATE State
00114 );
00115
00116
NTSTATUS
00117
IopTranslateBusAddress(
00118 IN PHYSICAL_ADDRESS SourceAddress,
00119 IN UCHAR SourceResourceType,
00120 OUT PPHYSICAL_ADDRESS TargetAddress,
00121 OUT PUCHAR TargetResourceType
00122 );
00123
00124
00125
00126
00127
00128
00129
#ifdef ALLOC_PRAGMA
00130
00131
#pragma alloc_text(PAGE, IopPortInitialize)
00132
#pragma alloc_text(PAGE, IopMemInitialize)
00133
#pragma alloc_text(PAGE, IopGenericUnpackRequirement)
00134
#pragma alloc_text(PAGE, IopGenericPackResource)
00135
#pragma alloc_text(PAGE, IopGenericScoreRequirement)
00136
#pragma alloc_text(PAGE, IopGenericUnpackResource)
00137
#pragma alloc_text(PAGE, IopPortBacktrackAllocation)
00138
#pragma alloc_text(PAGE, IopPortFindSuitableRange)
00139
#pragma alloc_text(PAGE, IopMemFindSuitableRange)
00140
#pragma alloc_text(PAGE, IopPortGetNextAlias)
00141
#pragma alloc_text(PAGE, IopPortAddAllocation)
00142
#pragma alloc_text(PAGE, IopPortIsAliasedRangeAvailable)
00143
#pragma alloc_text(PAGE, IopTranslateBusAddress)
00144
#endif // ALLOC_PRAGMA
00145
00146
00147 #define ADDRESS_SPACE_MEMORY 0x0
00148 #define ADDRESS_SPACE_PORT 0x1
00149 #define ADDRESS_SPACE_USER_MEMORY 0x2
00150 #define ADDRESS_SPACE_USER_PORT 0x3
00151 #define ADDRESS_SPACE_DENSE_MEMORY 0x4
00152 #define ADDRESS_SPACE_USER_DENSE_MEMORY 0x6
00153
00154
NTSTATUS
00155 IopTranslateBusAddress(
00156 IN PHYSICAL_ADDRESS SourceAddress,
00157 IN UCHAR SourceResourceType,
00158 OUT PPHYSICAL_ADDRESS TargetAddress,
00159 OUT PUCHAR TargetResourceType
00160 )
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 {
00183
NTSTATUS status = STATUS_UNSUCCESSFUL;
00184 ULONG sourceAddressSpace, targetAddressSpace;
00185 BOOLEAN translated;
00186
00187
PAGED_CODE();
00188
00189
00190
00191
00192
00193
if (SourceResourceType == CmResourceTypeMemory) {
00194 sourceAddressSpace =
ADDRESS_SPACE_MEMORY;
00195 }
else if (SourceResourceType == CmResourceTypePort) {
00196 sourceAddressSpace =
ADDRESS_SPACE_PORT;
00197 }
else {
00198
return STATUS_INVALID_PARAMETER;
00199 }
00200
00201
ARB_PRINT(
00202 2,
00203 (
"Translating %s address 0x%I64x => ",
00204 SourceResourceType == CmResourceTypeMemory ?
"Memory" :
"I/O",
00205 SourceAddress.QuadPart
00206 ));
00207
00208
00209
00210
00211
00212
00213
00214 targetAddressSpace = sourceAddressSpace;
00215 translated =
HalTranslateBusAddress(
00216 Isa,
00217 0,
00218 SourceAddress,
00219 &targetAddressSpace,
00220 TargetAddress
00221 );
00222
00223
if (!translated) {
00224
ARB_PRINT(2,(
"Translation failed!\n"));
00225
return STATUS_UNSUCCESSFUL;
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
if (targetAddressSpace ==
ADDRESS_SPACE_MEMORY
00239 || targetAddressSpace ==
ADDRESS_SPACE_USER_MEMORY
00240 || targetAddressSpace ==
ADDRESS_SPACE_DENSE_MEMORY
00241 || targetAddressSpace ==
ADDRESS_SPACE_USER_DENSE_MEMORY) {
00242 *TargetResourceType = CmResourceTypeMemory;
00243 }
else if (targetAddressSpace ==
ADDRESS_SPACE_PORT
00244 || targetAddressSpace ==
ADDRESS_SPACE_USER_PORT) {
00245 *TargetResourceType = CmResourceTypePort;
00246 }
else {
00247
ASSERT(0 &&
"Translation has returned an unknown address space");
00248 }
00249
00250
ARB_PRINT(
00251 2,
00252 (
"%s address 0x%I64x\n",
00253 *TargetResourceType == CmResourceTypeMemory ?
"Memory" :
"I/O",
00254 TargetAddress->QuadPart
00255 ));
00256
00257
return STATUS_SUCCESS;
00258
00259 }
00260
00261
00262
NTSTATUS
00263 IopGenericTranslateOrdering(
00264 OUT PIO_RESOURCE_DESCRIPTOR Target,
00265 IN PIO_RESOURCE_DESCRIPTOR Source
00266 )
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 {
00290
NTSTATUS status;
00291 UCHAR initialResourceType, minResourceType, maxResourceType;
00292
PAGED_CODE();
00293
00294
00295 *Target = *Source;
00296
00297
if (Source->Type != CmResourceTypeMemory
00298 && Source->Type != CmResourceTypePort) {
00299
return STATUS_SUCCESS;
00300 }
00301
00302 initialResourceType = Source->Type;
00303
00304
00305
00306
00307
00308 status =
IopTranslateBusAddress(Source->u.Generic.MinimumAddress,
00309 initialResourceType,
00310 &Target->u.Generic.MinimumAddress,
00311 &minResourceType
00312 );
00313
00314
if (
NT_SUCCESS(status)) {
00315
00316
00317
00318
00319
00320 status =
IopTranslateBusAddress(Source->u.Generic.MaximumAddress,
00321 initialResourceType,
00322 &Target->u.Generic.MaximumAddress,
00323 &maxResourceType
00324 );
00325
00326 }
00327
00328
00329
00330
00331
00332
00333
if (!
NT_SUCCESS(status)) {
00334 Target->Type = CmResourceTypeNull;
00335 }
else {
00336
ASSERT(minResourceType == maxResourceType);
00337 Target->Type = minResourceType;
00338 }
00339
00340
return STATUS_SUCCESS;
00341
00342 }
00343
00344
00345
00346
00347
00348
NTSTATUS
00349 IopPortInitialize(
00350 VOID
00351 )
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 {
00370
PAGED_CODE();
00371
00372
00373
00374
00375
00376
IopRootPortArbiter.
FindSuitableRange =
IopPortFindSuitableRange;
00377
IopRootPortArbiter.
AddAllocation =
IopPortAddAllocation;
00378
IopRootPortArbiter.
BacktrackAllocation =
IopPortBacktrackAllocation;
00379
00380
IopRootPortArbiter.
UnpackRequirement =
IopGenericUnpackRequirement;
00381
IopRootPortArbiter.
PackResource =
IopGenericPackResource;
00382
IopRootPortArbiter.
UnpackResource =
IopGenericUnpackResource;
00383
IopRootPortArbiter.
ScoreRequirement =
IopGenericScoreRequirement;
00384
00385
return ArbInitializeArbiterInstance(&
IopRootPortArbiter,
00386
NULL,
00387 CmResourceTypePort,
00388
L"RootPort",
00389
L"Root",
00390
IopGenericTranslateOrdering
00391 );
00392
00393 }
00394
00395
NTSTATUS
00396 IopMemInitialize(
00397 VOID
00398 )
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 {
00417
NTSTATUS status;
00418
00419
PAGED_CODE();
00420
00421
IopRootMemArbiter.
UnpackRequirement =
IopGenericUnpackRequirement;
00422
IopRootMemArbiter.
PackResource =
IopGenericPackResource;
00423
IopRootMemArbiter.
UnpackResource =
IopGenericUnpackResource;
00424
IopRootMemArbiter.
ScoreRequirement =
IopGenericScoreRequirement;
00425
00426
IopRootMemArbiter.
FindSuitableRange =
IopMemFindSuitableRange;
00427
00428 status =
ArbInitializeArbiterInstance(&
IopRootMemArbiter,
00429
NULL,
00430 CmResourceTypeMemory,
00431
L"RootMemory",
00432
L"Root",
00433
IopGenericTranslateOrdering
00434 );
00435
00436
if (!
NT_SUCCESS(status)) {
00437
return status;
00438 }
00439
00440
00441
00442
00443
00444
00445 status =
RtlAddRange(
IopRootMemArbiter.
Allocation,
00446 0,
00447
PAGE_SIZE,
00448 0,
00449 0,
00450
NULL,
00451
NULL
00452 );
00453
return status;
00454
00455 }
00456
00457
00458
00459
00460
00461
00462
NTSTATUS
00463 IopGenericUnpackRequirement(
00464 IN PIO_RESOURCE_DESCRIPTOR Descriptor,
00465 OUT PULONGLONG Minimum,
00466 OUT PULONGLONG Maximum,
00467 OUT PULONG Length,
00468 OUT PULONG Alignment
00469 )
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 {
00498
PAGED_CODE();
00499
ASSERT(Descriptor);
00500
ASSERT(Descriptor->Type == CmResourceTypePort
00501 || Descriptor->Type == CmResourceTypeMemory);
00502
00503
00504 *Minimum = (ULONGLONG) Descriptor->u.Generic.MinimumAddress.QuadPart;
00505 *Maximum = (ULONGLONG) Descriptor->u.Generic.MaximumAddress.QuadPart;
00506 *Length = Descriptor->u.Generic.Length;
00507 *Alignment = Descriptor->u.Generic.Alignment;
00508
00509
00510
00511
00512
00513
if (*Alignment == 0) {
00514 *Alignment = 1;
00515 }
00516
00517
00518
00519
00520
00521
if (Descriptor->Type == CmResourceTypeMemory
00522 && Descriptor->Flags & CM_RESOURCE_MEMORY_24
00523 && Descriptor->u.Memory.MaximumAddress.QuadPart > 0xFFFFFF) {
00524 *Maximum = 0xFFFFFF;
00525 }
00526
00527
ARB_PRINT(2,
00528 (
"Unpacking %s requirement %p => 0x%I64x-0x%I64x length 0x%x alignment 0x%x\n",
00529 Descriptor->Type == CmResourceTypePort ?
"port" :
"memory",
00530 Descriptor,
00531 *Minimum,
00532 *Maximum,
00533 *Length,
00534 *Alignment
00535 ));
00536
00537
return STATUS_SUCCESS;
00538
00539 }
00540
00541 LONG
00542 IopGenericScoreRequirement(
00543 IN PIO_RESOURCE_DESCRIPTOR Descriptor
00544 )
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 {
00566 LONG score;
00567 ULONGLONG start, end;
00568 LONGLONG bigscore;
00569 ULONG alignment;
00570
00571
PAGED_CODE();
00572
00573
#define MAX_SCORE MAXLONG
00574
00575
ASSERT(Descriptor);
00576
ASSERT((Descriptor->Type == CmResourceTypePort) ||
00577 (Descriptor->Type == CmResourceTypeMemory));
00578
00579 alignment = Descriptor->u.Generic.Alignment;
00580
00581
00582
00583
00584
00585
00586
00587
if (alignment == 0 &&
00588 ((Descriptor->Type == CmResourceTypePort) ||
00589 (Descriptor->Type == CmResourceTypeMemory))) {
00590 alignment = 1;
00591 }
00592
00593
00594
00595 start =
ALIGN_ADDRESS_UP(
00596 Descriptor->u.Generic.MinimumAddress.QuadPart,
00597 alignment
00598 );
00599
00600 end = Descriptor->u.Generic.MaximumAddress.QuadPart;
00601
00602
00603
00604
00605
00606
00607 bigscore = (((end - Descriptor->u.Generic.Length + 1) - start)
00608 / alignment) + 1;
00609
00610 score = (LONG)bigscore;
00611
if (bigscore < 0) {
00612 score = -1;
00613 }
else if (bigscore >
MAX_SCORE) {
00614 score =
MAX_SCORE;
00615 }
00616
00617
ARB_PRINT(2,
00618 (
"Scoring port resource %p(0x%I64x-0x%I64x) => %i\n",
00619 Descriptor->Type == CmResourceTypePort ?
"port" :
"memory",
00620 Descriptor,
00621 Descriptor->u.Generic.MinimumAddress.QuadPart,
00622 end,
00623 score
00624 ));
00625
00626
return score;
00627 }
00628
00629
NTSTATUS
00630 IopGenericPackResource(
00631 IN PIO_RESOURCE_DESCRIPTOR Requirement,
00632 IN ULONGLONG Start,
00633 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
00634 )
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 {
00657
00658
PAGED_CODE();
00659
ASSERT(Descriptor);
00660
ASSERT(Requirement);
00661
ASSERT(Requirement->Type == CmResourceTypePort
00662 || Requirement->Type == CmResourceTypeMemory);
00663
00664 Descriptor->Type = Requirement->Type;
00665 Descriptor->Flags = Requirement->Flags;
00666 Descriptor->ShareDisposition = Requirement->ShareDisposition;
00667 Descriptor->u.Generic.Start.QuadPart =
Start;
00668 Descriptor->u.Generic.Length = Requirement->u.Generic.Length;
00669
00670
ARB_PRINT(2,
00671 (
"Packing %s resource %p => 0x%I64x length 0x%x\n",
00672 Descriptor->Type == CmResourceTypePort ?
"port" :
"memory",
00673 Descriptor,
00674 Descriptor->u.Port.Start.QuadPart,
00675 Descriptor->u.Port.Length
00676 ));
00677
00678
return STATUS_SUCCESS;
00679 }
00680
00681
NTSTATUS
00682 IopGenericUnpackResource(
00683 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
00684 OUT PULONGLONG Start,
00685 OUT PULONG Length
00686 )
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 {
00709
00710
PAGED_CODE();
00711
ASSERT(Descriptor);
00712
ASSERT(Descriptor->Type == CmResourceTypePort
00713 || Descriptor->Type == CmResourceTypeMemory);
00714
00715 *
Start = Descriptor->u.Generic.Start.QuadPart;
00716 *Length = Descriptor->u.Generic.Length;
00717
00718
ARB_PRINT(2,
00719 (
"Unpacking %s resource %p => 0x%I64x Length 0x%x\n",
00720 Descriptor->Type == CmResourceTypePort ?
"port" :
"memory",
00721 Descriptor,
00722 *
Start,
00723 *Length
00724 ));
00725
00726
return STATUS_SUCCESS;
00727
00728 }
00729
#if 0
00730
NTSTATUS
00731 IopPortRetestAllocation(
00732 IN PARBITER_INSTANCE Arbiter,
00733 IN OUT PLIST_ENTRY ArbitrationList
00734 )
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760 {
00761
NTSTATUS status;
00762
PARBITER_LIST_ENTRY current;
00763 PIO_RESOURCE_DESCRIPTOR alternative;
00764 ULONGLONG start;
00765 ULONG length;
00766
00767
PAGED_CODE();
00768
00769
00770
00771
00772
00773
ARB_PRINT(3, (
"Retest: Copy current allocation\n"));
00774 status =
RtlCopyRangeList(Arbiter->PossibleAllocation, Arbiter->Allocation);
00775
00776
if (!
NT_SUCCESS(status)) {
00777
goto cleanup;
00778 }
00779
00780
00781
00782
00783
00784
00785
FOR_ALL_IN_LIST(
ARBITER_LIST_ENTRY, ArbitrationList, current) {
00786
00787
ARB_PRINT(2, (
"Retest: Delete 0x%08x's resources\n", current->
PhysicalDeviceObject));
00788
00789 status =
RtlDeleteOwnersRanges(Arbiter->PossibleAllocation,
00790 (PVOID) current->
PhysicalDeviceObject
00791 );
00792
00793
if (!
NT_SUCCESS(status)) {
00794
goto cleanup;
00795 }
00796 }
00797
00798
00799
00800
00801
00802
FOR_ALL_IN_LIST(
ARBITER_LIST_ENTRY, ArbitrationList, current) {
00803
00804
ASSERT(current->
Assignment);
00805
00806 status = Arbiter->UnpackResource(current->
Assignment,
00807 &start,
00808 &length
00809 );
00810
00811
ASSERT(
NT_SUCCESS(status));
00812
00813
00814
00815
00816
00817
00818
00819
if (length != 0) {
00820
00821 status =
RtlAddRange(
00822 Arbiter->PossibleAllocation,
00823 start,
00824 start + length - 1,
00825 0,
00826 RTL_RANGE_LIST_ADD_IF_CONFLICT +
00827 (current->
Assignment->ShareDisposition == CmResourceShareShared ?
00828 RTL_RANGE_LIST_ADD_SHARED : 0),
00829 NULL,
00830 current->
PhysicalDeviceObject
00831 );
00832
00833
ASSERT(
NT_SUCCESS(status));
00834
00835
00836
00837
00838
00839
00840 alternative = current->
SelectedAlternative;
00841
00842
00843
00844
00845
00846
if (alternative->Flags & CM_RESOURCE_PORT_10_BIT_DECODE
00847 || alternative->Flags & CM_RESOURCE_PORT_12_BIT_DECODE) {
00848
00849 ULONGLONG alias = start;
00850 BOOLEAN shared = current->
Assignment->ShareDisposition ==
00851 CmResourceShareShared;
00852
00853
ARB_PRINT(3, (
"Adding aliases\n"));
00854
00855
while (
IopPortGetNextAlias(alternative->Flags,
00856 alias,
00857 &alias)) {
00858
00859 status =
RtlAddRange(
00860 Arbiter->PossibleAllocation,
00861 alias,
00862 alias + length - 1,
00863 ARBITER_RANGE_ALIAS,
00864 RTL_RANGE_LIST_ADD_IF_CONFLICT +
00865 (shared ? RTL_RANGE_LIST_SHARED_OK : 0),
00866 NULL,
00867 current->
PhysicalDeviceObject
00868 );
00869
00870
00871
00872
00873
00874
00875
ASSERT(
NT_SUCCESS(status));
00876 }
00877 }
00878 }
00879 }
00880
00881
return status;
00882
00883 cleanup:
00884
00885
RtlFreeRangeList(Arbiter->PossibleAllocation);
00886
return status;
00887 }
00888
#endif
00889
VOID
00890 IopPortBacktrackAllocation(
00891 IN PARBITER_INSTANCE Arbiter,
00892 IN
PARBITER_ALLOCATION_STATE State
00893 )
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918 {
00919
00920
NTSTATUS status;
00921 ULONGLONG alias = State->Start;
00922
00923
PAGED_CODE();
00924
00925
00926
00927
00928
00929
ARB_PRINT(2, (
"\t\tDeleting aliases\n"));
00930
00931
while (
IopPortGetNextAlias(State->CurrentAlternative->Flags,
00932 alias,
00933 &alias)) {
00934
00935 status =
RtlDeleteRange(
00936 Arbiter->PossibleAllocation,
00937 alias,
00938 alias + State->CurrentAlternative->Length - 1,
00939 State->Entry->PhysicalDeviceObject
00940 );
00941
00942
00943
00944
00945
00946
ASSERT(
NT_SUCCESS(status));
00947 }
00948
00949
00950
00951
00952
00953
ArbBacktrackAllocation(Arbiter, State);
00954
00955 }
00956
00957
00958 BOOLEAN
00959 IopPortFindSuitableRange(
00960 PARBITER_INSTANCE Arbiter,
00961
PARBITER_ALLOCATION_STATE State
00962 )
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984 {
00985
NTSTATUS status;
00986 UCHAR userFlagsMask = 0;
00987
00988
PAGED_CODE();
00989
00990
00991
00992
00993
00994
00995
if (State->
CurrentAlternative->
Length == 0) {
00996 State->
End = State->
Start;
00997
return TRUE;
00998 }
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
if (State->
Entry->
RequestSource ==
ArbiterRequestLegacyReported
01010 || State->
Entry->
RequestSource ==
ArbiterRequestLegacyAssigned
01011 || State->
Entry->
Flags &
ARBITER_FLAG_BOOT_CONFIG) {
01012
01013 userFlagsMask =
ARBITER_RANGE_BOOT_ALLOCATED;
01014 }
01015
01016
01017
01018
01019
01020
while (State->
CurrentMinimum <= State->
CurrentMaximum) {
01021
01022
01023
01024
01025
01026 status =
RtlFindRange(
01027 Arbiter->PossibleAllocation,
01028 State->
CurrentMinimum,
01029 State->
CurrentMaximum,
01030 State->
CurrentAlternative->
Length,
01031 State->
CurrentAlternative->
Alignment,
01032 State->
CurrentAlternative->
Flags &
01033
ARBITER_ALTERNATIVE_FLAG_SHARED ?
01034 RTL_RANGE_LIST_SHARED_OK : 0,
01035 userFlagsMask,
01036 Arbiter->ConflictCallbackContext,
01037 Arbiter->ConflictCallback,
01038 &State->
Start
01039 );
01040
01041
01042
01043
01044
01045
if (
NT_SUCCESS(status)
01046 || Arbiter->OverrideConflict(Arbiter, State)) {
01047
01048 State->
End = State->
Start + State->
CurrentAlternative->
Length - 1;
01049
01050
01051
01052
01053
if (
IopPortIsAliasedRangeAvailable(Arbiter, State)) {
01054
01055
01056
01057
01058
01059
return TRUE;
01060
01061 }
else {
01062
01063
01064
01065
01066
01067 State->
Start += State->
CurrentAlternative->
Length;
01068
01069
continue;
01070 }
01071 }
else {
01072
01073
01074
01075
01076
01077
break;
01078 }
01079 }
01080
01081
return FALSE;
01082 }
01083
01084
01085
01086 BOOLEAN
01087 IopPortGetNextAlias(
01088 ULONG IoDescriptorFlags,
01089 ULONGLONG LastAlias,
01090 PULONGLONG NextAlias
01091 )
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113 {
01114 ULONGLONG next;
01115
01116
PAGED_CODE();
01117
01118
if (IoDescriptorFlags & CM_RESOURCE_PORT_10_BIT_DECODE) {
01119 next = LastAlias + (1 << 10);
01120 }
else if (IoDescriptorFlags & CM_RESOURCE_PORT_12_BIT_DECODE) {
01121 next = LastAlias + (1 << 12);
01122 }
else {
01123
01124
01125
01126
01127
01128
01129
return FALSE;
01130 }
01131
01132
01133
01134
01135
01136
if (next >
MAX_ALIAS_PORT) {
01137
return FALSE;
01138 }
else {
01139 *NextAlias = next;
01140
return TRUE;
01141 }
01142 }
01143
01144
01145
VOID
01146 IopPortAddAllocation(
01147 IN PARBITER_INSTANCE Arbiter,
01148 IN
PARBITER_ALLOCATION_STATE State
01149 )
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171 {
01172
NTSTATUS status;
01173 ULONGLONG alias;
01174 BOOLEAN isAlias;
01175
01176
PAGED_CODE();
01177
01178
ASSERT(Arbiter);
01179
ASSERT(State);
01180
01181 status =
RtlAddRange(Arbiter->PossibleAllocation,
01182 State->Start,
01183 State->End,
01184 State->RangeAttributes,
01185 RTL_RANGE_LIST_ADD_IF_CONFLICT +
01186 (State->CurrentAlternative->Flags &
ARBITER_ALTERNATIVE_FLAG_SHARED
01187 ? RTL_RANGE_LIST_ADD_SHARED : 0),
01188
NULL,
01189 State->Entry->PhysicalDeviceObject
01190 );
01191
01192
ASSERT(
NT_SUCCESS(status));
01193
01194
01195
01196
01197
01198 alias = State->Start;
01199
ARB_PRINT(2, (
"Adding aliases\n"));
01200
01201
while (
IopPortGetNextAlias(State->CurrentAlternative->Descriptor->Flags,
01202 alias,
01203 &alias)) {
01204
01205 status =
RtlAddRange(Arbiter->PossibleAllocation,
01206 alias,
01207 alias + State->CurrentAlternative->Length - 1,
01208 (UCHAR) (State->RangeAttributes |
ARBITER_RANGE_ALIAS),
01209 RTL_RANGE_LIST_ADD_IF_CONFLICT +
01210 (State->CurrentAlternative->Flags &
ARBITER_ALTERNATIVE_FLAG_SHARED
01211 ? RTL_RANGE_LIST_ADD_SHARED : 0),
01212
NULL,
01213 State->Entry->PhysicalDeviceObject
01214 );
01215
01216
01217
01218
01219
01220
01221
ASSERT(
NT_SUCCESS(status));
01222 }
01223 }
01224
01225
01226 BOOLEAN
01227 IopPortIsAliasedRangeAvailable(
01228 PARBITER_INSTANCE Arbiter,
01229
PARBITER_ALLOCATION_STATE State
01230 )
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251 {
01252
NTSTATUS status;
01253 ULONGLONG alias = State->
Start;
01254 BOOLEAN aliasAvailable;
01255 UCHAR userFlagsMask = 0;
01256
01257
PAGED_CODE();
01258
01259
#if defined(BUGFEST_HACKS)
01260
01261
01262
01263
01264
return TRUE;
01265
#endif
01266
01267
01268
01269
01270
01271
01272
if (State->
Entry->
RequestSource ==
ArbiterRequestLegacyReported
01273 || State->
Entry->
RequestSource ==
ArbiterRequestLegacyAssigned) {
01274
01275 userFlagsMask |=
ARBITER_RANGE_BOOT_ALLOCATED;
01276 }
01277
01278
while (
IopPortGetNextAlias(State->
CurrentAlternative->
Descriptor->Flags,
01279 alias,
01280 &alias)) {
01281
01282 status =
RtlIsRangeAvailable(
01283 Arbiter->PossibleAllocation,
01284 alias,
01285 alias + State->
CurrentAlternative->
Length - 1,
01286 State->
CurrentAlternative->
Flags &
ARBITER_ALTERNATIVE_FLAG_SHARED ?
01287 RTL_RANGE_LIST_SHARED_OK : 0,
01288 userFlagsMask,
01289 Arbiter->ConflictCallbackContext,
01290 Arbiter->ConflictCallback,
01291 &aliasAvailable
01292 );
01293
01294
ASSERT(
NT_SUCCESS(status));
01295
01296
if (!aliasAvailable) {
01297
01298
ARBITER_ALLOCATION_STATE tempState;
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309 RtlCopyMemory(&tempState, State,
sizeof(
ARBITER_ALLOCATION_STATE));
01310
01311 tempState.
CurrentMinimum = alias;
01312 tempState.
CurrentMaximum = alias + State->
CurrentAlternative->
Length - 1;
01313
01314
if (Arbiter->OverrideConflict(Arbiter, &tempState)) {
01315
01316
01317
01318
01319
01320
continue;
01321
01322 }
01323
01324
01325
01326
01327
01328
ARB_PRINT(2,
01329 (
"\t\tAlias 0x%x-0x%x not available\n",
01330 alias,
01331 alias + State->
CurrentAlternative->
Length - 1
01332 ));
01333
01334
return FALSE;
01335 }
01336 }
01337
01338
return TRUE;
01339 }
01340
01341 BOOLEAN
01342 IopMemFindSuitableRange(
01343 PARBITER_INSTANCE Arbiter,
01344
PARBITER_ALLOCATION_STATE State
01345 )
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367 {
01368
01369
01370
01371
01372
01373
if (State->
Entry->
Flags &
ARBITER_FLAG_BOOT_CONFIG) {
01374 State->
RangeAvailableAttributes |=
ARBITER_RANGE_BOOT_ALLOCATED;
01375 }
01376
01377
01378
01379
01380
01381
return ArbFindSuitableRange(Arbiter, State);
01382 }
01383