📄 mmcpci.c
字号:
CfgData.VendorID = PCI_INVALID_VENDORID;
PciReadConfig(BusNumber,
SlotNumber,
&CfgData,
0,
PCI_COMMON_HDR_LENGTH);
if (CfgData.VendorID == PCI_INVALID_VENDORID)
return STATUS_UNSUCCESSFUL;
/* save a copy of the configuration space */
RtlCopyMemory(&OrigCfgData, &CfgData, PCI_COMMON_HDR_LENGTH);
switch (PCI_CONFIG_TYPE(&CfgData)) {
case 0:
for (i=0; i<PCI_TYPE0_ADDRESSES; i++) {
BaseAddress[i] = &CfgData.u.type0.BaseAddresses[i];
OrigAddress[i] = &OrigCfgData.u.type0.BaseAddresses[i];
}
BaseAddress[PCI_TYPE0_ADDRESSES] = &CfgData.u.type0.ROMBaseAddress;
OrigAddress[PCI_TYPE0_ADDRESSES] = &OrigCfgData.u.type0.ROMBaseAddress;
RomIndex = PCI_TYPE0_ADDRESSES;
NoBaseAddress = PCI_TYPE0_ADDRESSES + 1;
break;
case 1:
for (i=0; i<PCI_TYPE1_ADDRESSES; i++) {
BaseAddress[i] = &CfgData.u.type1.BaseAddresses[i];
OrigAddress[i] = &OrigCfgData.u.type1.BaseAddresses[i];
}
BaseAddress[PCI_TYPE1_ADDRESSES] = &CfgData.u.type1.ExpansionROMBase;
OrigAddress[PCI_TYPE1_ADDRESSES] = &OrigCfgData.u.type1.ExpansionROMBase;
RomIndex = PCI_TYPE1_ADDRESSES;
NoBaseAddress = PCI_TYPE1_ADDRESSES + 1;
break;
default:
return STATUS_UNSUCCESSFUL;
}
EnableRomBase = TRUE;
if ((*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED) == 0) {
EnableRomBase = FALSE;
NoBaseAddress -= 1;
}
i = sizeof(IO_RESOURCE_REQUIREMENTS_LIST)
+ sizeof(IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2;
WorkingPool = (PUCHAR)LocalAlloc(LMEM_FIXED, i);
if (WorkingPool == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(WorkingPool, i);
CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST)WorkingPool;
/* write all 1s to each base address register to determine its block range */
for (i=0; i<NoBaseAddress; i++)
*BaseAddress[i] = 0xffffffff;
/* turn off address decoding while trying to determine the block size */
CfgData.Command &= ~(USHORT)(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
*BaseAddress[RomIndex] &= ~(ULONG)PCI_ROMADDRESS_ENABLED;
PciWriteConfig(BusNumber,
SlotNumber,
&CfgData,
0,
PCI_COMMON_HDR_LENGTH);
PciReadConfig(BusNumber,
SlotNumber,
&CfgData,
0,
PCI_COMMON_HDR_LENGTH);
/* build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device */
CompleteList->InterfaceType = PCIBus;
CompleteList->BusNumber = BusNumber;
CompleteList->SlotNumber = SlotNumber.u.AsULONG;
CompleteList->AlternativeLists = 1;
CompleteList->List[0].Version = 1;
CompleteList->List[0].Revision = 1;
CompleteList->List[0].Count = 0;
IoDescriptor = CompleteList->List[0].Descriptors;
RequestedInterrupt = FALSE;
if (CfgData.u.type0.InterruptPin != 0
&& CfgData.u.type0.InterruptLine != 0xff) {
RequestedInterrupt = TRUE;
CompleteList->List[0].Count++;
IoDescriptor->Option = 0;
IoDescriptor->Type = CmResourceTypeInterrupt;
IoDescriptor->ShareDisposition = CmResourceShareShared;
IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
IoDescriptor->u.Interrupt.MinimumVector = CfgData.u.type0.InterruptLine;
IoDescriptor->u.Interrupt.MaximumVector = 0xff;
IoDescriptor++;
}
/* mask off reserved bits */
*BaseAddress[RomIndex] &= ~0xfffff800;
i = 0;
while (i < NoBaseAddress) {
ULONG Address;
Address = *BaseAddress[i];
if (Address != 0) {
ULONG Length;
ULONG MaxAddress;
BOOLEAN IoSpace;
BOOLEAN Address64;
IoSpace = (Address & PCI_ADDRESS_IO_SPACE) != 0 ? TRUE : FALSE;
Address64 = (Address && PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT
? TRUE : FALSE;
Length = 1 << (IoSpace ? 2 : 4);
while ((Address & Length) == 0)
Length <<= 1;
MaxAddress = Length;
while (MaxAddress != 0 && (Address & MaxAddress) != 0)
MaxAddress <<= 1;
MaxAddress--;
DBGCHK(TEXT("NTCOMPAT"), (Length & ~MaxAddress) == 0);
IoDescriptor->Option = 0;
if (IoSpace) {
if (!Address64 && (OrigCfgData.Command & PCI_ENABLE_IO_SPACE) != 0) {
IoDescriptor->Option = IO_RESOURCE_PREFERRED;
IoDescriptor->Type = CmResourceTypePort;
IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
IoDescriptor->u.Port.Length = Length;
IoDescriptor->u.Port.Alignment = Length;
IoDescriptor->u.Port.MinimumAddress.LowPart
= *OrigAddress[i] & 0xfffffffc;
IoDescriptor->u.Port.MaximumAddress.LowPart
= IoDescriptor->u.Port.MinimumAddress.LowPart + Length - 1;
CompleteList->List[0].Count++;
IoDescriptor++;
IoDescriptor->Option = IO_RESOURCE_ALTERNATIVE;
}
IoDescriptor->Type = CmResourceTypePort;
IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
IoDescriptor->u.Port.Length = Length;
IoDescriptor->u.Port.Alignment = Length;
IoDescriptor->u.Port.MinimumAddress.LowPart = 0;
IoDescriptor->u.Port.MaximumAddress.LowPart = MaxAddress;
} else {
IoDescriptor->Flags = i == RomIndex
? CM_RESOURCE_MEMORY_READ_ONLY
: CM_RESOURCE_MEMORY_READ_WRITE;
if (Address & PCI_ADDRESS_MEMORY_PREFETCHABLE)
IoDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
if (!Address64
&& (i == RomIndex
|| (OrigCfgData.Command & PCI_ENABLE_MEMORY_SPACE))) {
USHORT Flags = IoDescriptor->Flags;
IoDescriptor->Option = IO_RESOURCE_PREFERRED;
IoDescriptor->Type = CmResourceTypeMemory;
IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
IoDescriptor->u.Memory.Length = Length;
IoDescriptor->u.Memory.Alignment = Length;
IoDescriptor->u.Memory.MinimumAddress.LowPart
= *OrigAddress[i] & 0xfffffff0;
IoDescriptor->u.Memory.MaximumAddress.LowPart
= IoDescriptor->u.Memory.MinimumAddress.LowPart + Length - 1;
CompleteList->List[0].Count++;
IoDescriptor++;
IoDescriptor->Flags = Flags;
IoDescriptor->Option = IO_RESOURCE_ALTERNATIVE;
}
IoDescriptor->Type = CmResourceTypeMemory;
IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
IoDescriptor->u.Memory.Length = Length;
IoDescriptor->u.Memory.Alignment = Length;
IoDescriptor->u.Memory.MinimumAddress.LowPart = 0;
IoDescriptor->u.Memory.MaximumAddress.LowPart
= (Address & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_20BIT
? 0x000fffff : MaxAddress;
}
CompleteList->List[0].Count++;
IoDescriptor++;
if (Address64)
i++;
}
i++;
}
CompleteList->ListSize = (ULONG)IoDescriptor - (ULONG)CompleteList;
/* restore settings */
PciWriteConfig(BusNumber,
SlotNumber,
&OrigCfgData.RevisionID,
FIELD_OFFSET(PCI_COMMON_CONFIG, RevisionID),
PCI_COMMON_HDR_LENGTH
- FIELD_OFFSET(PCI_COMMON_CONFIG, RevisionID));
PciWriteConfig(BusNumber,
SlotNumber,
&OrigCfgData,
0,
FIELD_OFFSET(PCI_COMMON_CONFIG, RevisionID));
/*
if (IoAssignResources(RegistryPath,
DriverClassName,
DriverObject,
DeviceObject,
CompleteList,
AllocatedResources) != STATUS_SUCCESS) {
LocalFree((HLOCAL)WorkingPool);
return STATUS_UNSUCCESSFUL;
}
*/
CmDescriptor
= (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
if (RequestedInterrupt) {
/* IoAssignResources preserves the resource order */
/* type0 and type1 overlay InterruptLine */
CfgData.u.type0.InterruptLine = (UCHAR)CmDescriptor->u.Interrupt.Vector;
CmDescriptor++;
}
i = 0;
while (i < NoBaseAddress) {
ULONG Address;
Address = *BaseAddress[i];
if (Address != 0) {
*BaseAddress[i] = Address & PCI_ADDRESS_IO_SPACE
? CmDescriptor->u.Port.Start.LowPart
: CmDescriptor->u.Memory.Start.LowPart;
CmDescriptor++;
if ((Address && PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)
i++;
}
i++;
}
/* turn address decoding off and write assigned resources to the
* configuration space */
PciWriteConfig(BusNumber,
SlotNumber,
&CfgData,
0,
PCI_COMMON_HDR_LENGTH);
/* enable address decoding */
if (EnableRomBase && *BaseAddress[RomIndex] != 0) {
*BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
/* type0 and type1 overlay ROMBaseAddress */
PciWriteConfig(BusNumber,
SlotNumber,
BaseAddress[RomIndex],
(ULONG)BaseAddress[RomIndex] - (ULONG)&CfgData,
4);
}
CfgData.Command |= PCI_ENABLE_IO_SPACE
| PCI_ENABLE_MEMORY_SPACE
| PCI_ENABLE_BUS_MASTER;
PciWriteConfig(BusNumber,
SlotNumber,
&CfgData.Command,
FIELD_OFFSET(PCI_COMMON_CONFIG, Command),
4);
LocalFree((HLOCAL)WorkingPool);
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -