1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/** @file
Base IPC library implementation.
Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Base.h>
#include <SaCommonDefinitions.h>
#include <PlatformBaseAddresses.h>
#include <ScRegs/RegsPmc.h>
#include "InternalIpcLib.h"
/**
Checks the IPC channel is available for a new request.
@retval EFI_SUCCESS Ready for a new IPC.
@retval EFI_NOT_READY Not ready for a new IPC.
**/
EFI_STATUS
EFIAPI
ReadyForNewIpc (
VOID
)
{
UINT32 PciCfgReg;
UINT32 Value = 0;
UINT32 Addr32;
UINTN PmcIpc1RegBaseAddr = 0;
PciCfgReg = (UINT32) MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PMC_IPC1, PCI_FUNCTION_NUMBER_PMC_IPC1, 0x10); //Bar0 Reg
Addr32 = MmioRead32 (PciCfgReg) & 0xFFFFFFF0;
PciCfgReg = (UINT32) MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PMC_IPC1, PCI_FUNCTION_NUMBER_PMC_IPC1, 0x4); //Sts Reg
Value = MmioRead32 (PciCfgReg);
if (Addr32 != 0 && Addr32 != 0xFFFFFFF0 && ((Value & 0x06) == 0x06)) {
PmcIpc1RegBaseAddr = Addr32;
} else {
return EFI_NOT_READY;
}
return InternalReadyForNewIpc (PmcIpc1RegBaseAddr);
}
/**
Sends an IPC from the x86 CPU to the SCU and waits for the SCU to process the
specified opcode.
@param[in] Command The Command identifier to send in the IPC packet.
@param[in] SubCommand The SubCommand identifier to send in the IPC packet.
@param[in, out] Buffer Pointer to buffer associated with MessageId. This is an optional
patrametert that may be NULL for some MessageId values.
@param[in, out] BufferSize The size, in bytes, of Buffer. Ignored if Buffer is NULL.
@retval IPC_STATUS
**/
EFI_STATUS
EFIAPI
IpcSendCommandEx (
IN UINT32 Command,
IN UINT8 SubCommand,
IN OUT VOID *Buffer, OPTIONAL
IN OUT UINTN BufferSize
)
{
UINT32 PciCfgReg;
UINT32 Value = 0;
UINT32 Addr32;
UINTN PmcIpc1RegBaseAddr = 0;
PciCfgReg = (UINT32) MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PMC_IPC1, PCI_FUNCTION_NUMBER_PMC_IPC1, 0x10); //Bar0 Reg
Addr32 = MmioRead32 (PciCfgReg) & 0xFFFFFFF0;
PciCfgReg = (UINT32) MmPciAddress(0, 0, PCI_DEVICE_NUMBER_PMC_IPC1, PCI_FUNCTION_NUMBER_PMC_IPC1, 0x4); //Sts Reg
Value = MmioRead32 (PciCfgReg);
if (Addr32 != 0 && Addr32 != 0xFFFFFFF0 && ((Value & 0x06) == 0x06)) {
PmcIpc1RegBaseAddr = Addr32;
} else {
DEBUG ((DEBUG_ERROR, "Error IPC1 command failed MMIO address %x, status =%x \n", Addr32, Value));
return EFI_NOT_READY;
}
return InternalIpcSendCommandEx (PmcIpc1RegBaseAddr, Command, SubCommand, Buffer, BufferSize);
}
/**
Sends an IPC from the x86 CPU to the PMC and waits for the PMC to process the
specified opcode.
!! Use it only when you are sure that IPC PCI config space is no longer valid !!
@param[in] PciBar0 PCI config BAR0 for IPC.
@param[in] Command The Command identifier to send in the IPC packet.
@param[in] SubCommand The SubCommand identifier to send in the IPC packet.
@param[in, out] Buffer Pointer to buffer associated with MessageId. This is an optional
patrametert that may be NULL for some MessageId values.
@param[in, out] BufferSize The size, in bytes, of Buffer. Ignored if Buffer is NULL.
**/
EFI_STATUS
EFIAPI
IpcSendCommandBar0Ex (
IN UINT32 PciBar0,
IN UINT32 Command,
IN UINT8 SubCommand,
IN OUT VOID *Buffer, OPTIONAL
IN OUT UINTN BufferSize
)
{
if (PciBar0 != 0 && PciBar0 != 0xFFFFFFF0) {
return InternalIpcSendCommandEx (PciBar0, Command, SubCommand, Buffer, BufferSize);
}
DEBUG ((DEBUG_ERROR, "IpcSendCommandBar0Ex Error IPC1 command failed, not valid address %x\n", PciBar0));
return EFI_NOT_READY;
}
|