1 /** @file
2 
3   Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4 
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "PciEmulation.h"
16 
17 BOOLEAN
PciRootBridgeMemAddressValid(IN PCI_ROOT_BRIDGE * Private,IN UINT64 Address)18 PciRootBridgeMemAddressValid (
19   IN PCI_ROOT_BRIDGE  *Private,
20   IN UINT64           Address
21   )
22 {
23   if ((Address >= Private->MemoryStart) && (Address < (Private->MemoryStart + Private->MemorySize))) {
24     return TRUE;
25   }
26 
27   return FALSE;
28 }
29 
30 
31 EFI_STATUS
PciRootBridgeIoMemRW(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINTN Count,IN BOOLEAN InStrideFlag,IN PTR In,IN BOOLEAN OutStrideFlag,OUT PTR Out)32 PciRootBridgeIoMemRW (
33   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
34   IN  UINTN                                  Count,
35   IN  BOOLEAN                                InStrideFlag,
36   IN  PTR                                    In,
37   IN  BOOLEAN                                OutStrideFlag,
38   OUT PTR                                    Out
39   )
40 {
41   UINTN  Stride;
42   UINTN  InStride;
43   UINTN  OutStride;
44 
45   Width     = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
46   Stride    = (UINTN)1 << Width;
47   InStride  = InStrideFlag  ? Stride : 0;
48   OutStride = OutStrideFlag ? Stride : 0;
49 
50   //
51   // Loop for each iteration and move the data
52   //
53   switch (Width) {
54   case EfiPciWidthUint8:
55     for (;Count > 0; Count--, In.Buffer += InStride, Out.Buffer += OutStride) {
56       *In.Ui8 = *Out.Ui8;
57     }
58     break;
59   case EfiPciWidthUint16:
60     for (;Count > 0; Count--, In.Buffer += InStride, Out.Buffer += OutStride) {
61       *In.Ui16 = *Out.Ui16;
62     }
63     break;
64   case EfiPciWidthUint32:
65     for (;Count > 0; Count--, In.Buffer += InStride, Out.Buffer += OutStride) {
66       *In.Ui32 = *Out.Ui32;
67     }
68     break;
69   default:
70     return EFI_INVALID_PARAMETER;
71   }
72 
73   return EFI_SUCCESS;
74 }
75 
76 EFI_STATUS
PciRootBridgeIoPciRW(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN BOOLEAN Write,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 UserAddress,IN UINTN Count,IN OUT VOID * UserBuffer)77 PciRootBridgeIoPciRW (
78   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
79   IN BOOLEAN                                Write,
80   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
81   IN UINT64                                 UserAddress,
82   IN UINTN                                  Count,
83   IN OUT VOID                               *UserBuffer
84   )
85 {
86   return EFI_SUCCESS;
87 }
88 
89 /**
90   Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
91 
92   @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
93   @param  Width                 Signifies the width of the memory operations.
94   @param  Address               The base address of the memory operations.
95   @param  Count                 The number of memory operations to perform.
96   @param  Buffer                For read operations, the destination buffer to store the results. For write
97                                 operations, the source buffer to write data from.
98 
99   @retval EFI_SUCCESS           The data was read from or written to the PCI root bridge.
100   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
101   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
102 
103 **/
104 EFI_STATUS
105 EFIAPI
PciRootBridgeIoMemRead(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)106 PciRootBridgeIoMemRead (
107   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
108   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
109   IN     UINT64                                 Address,
110   IN     UINTN                                  Count,
111   IN OUT VOID                                   *Buffer
112   )
113 {
114   PCI_ROOT_BRIDGE   *Private;
115   UINTN             AlignMask;
116   PTR               In;
117   PTR               Out;
118 
119   if ( Buffer == NULL ) {
120     return EFI_INVALID_PARAMETER;
121   }
122 
123   Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
124 
125   if (!PciRootBridgeMemAddressValid (Private, Address)) {
126     return EFI_INVALID_PARAMETER;
127   }
128 
129   AlignMask = (1 << (Width & 0x03)) - 1;
130   if (Address & AlignMask) {
131     return EFI_INVALID_PARAMETER;
132   }
133 
134   In.Buffer  = Buffer;
135   Out.Buffer = (VOID *)(UINTN) Address;
136 
137   switch (Width) {
138   case EfiPciWidthUint8:
139   case EfiPciWidthUint16:
140   case EfiPciWidthUint32:
141   case EfiPciWidthUint64:
142     return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
143 
144   case EfiPciWidthFifoUint8:
145   case EfiPciWidthFifoUint16:
146   case EfiPciWidthFifoUint32:
147   case EfiPciWidthFifoUint64:
148     return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
149 
150   case EfiPciWidthFillUint8:
151   case EfiPciWidthFillUint16:
152   case EfiPciWidthFillUint32:
153   case EfiPciWidthFillUint64:
154     return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
155 
156   default:
157     break;
158   }
159 
160   return EFI_INVALID_PARAMETER;
161 }
162 
163 /**
164   Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
165 
166   @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
167   @param  Width                 Signifies the width of the memory operations.
168   @param  Address               The base address of the memory operations.
169   @param  Count                 The number of memory operations to perform.
170   @param  Buffer                For read operations, the destination buffer to store the results. For write
171                                 operations, the source buffer to write data from.
172 
173   @retval EFI_SUCCESS           The data was read from or written to the PCI root bridge.
174   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
175   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
176 
177 **/
178 EFI_STATUS
179 EFIAPI
PciRootBridgeIoMemWrite(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)180 PciRootBridgeIoMemWrite (
181   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
182   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
183   IN     UINT64                                 Address,
184   IN     UINTN                                  Count,
185   IN OUT VOID                                   *Buffer
186   )
187 {
188   PCI_ROOT_BRIDGE *Private;
189   UINTN  AlignMask;
190   PTR    In;
191   PTR    Out;
192 
193   if ( Buffer == NULL ) {
194     return EFI_INVALID_PARAMETER;
195   }
196 
197   Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
198 
199   if (!PciRootBridgeMemAddressValid (Private, Address)) {
200     return EFI_INVALID_PARAMETER;
201   }
202 
203   AlignMask = (1 << (Width & 0x03)) - 1;
204   if (Address & AlignMask) {
205     return EFI_INVALID_PARAMETER;
206   }
207 
208   In.Buffer  = (VOID *)(UINTN) Address;
209   Out.Buffer = Buffer;
210 
211   switch (Width) {
212   case EfiPciWidthUint8:
213   case EfiPciWidthUint16:
214   case EfiPciWidthUint32:
215   case EfiPciWidthUint64:
216     return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
217 
218   case EfiPciWidthFifoUint8:
219   case EfiPciWidthFifoUint16:
220   case EfiPciWidthFifoUint32:
221   case EfiPciWidthFifoUint64:
222     return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
223 
224   case EfiPciWidthFillUint8:
225   case EfiPciWidthFillUint16:
226   case EfiPciWidthFillUint32:
227   case EfiPciWidthFillUint64:
228     return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
229 
230   default:
231     break;
232   }
233 
234   return EFI_INVALID_PARAMETER;
235 }
236 
237 /**
238   Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
239 
240   @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
241   @param  Width                 Signifies the width of the memory operations.
242   @param  Address               The base address of the memory operations.
243   @param  Count                 The number of memory operations to perform.
244   @param  Buffer                For read operations, the destination buffer to store the results. For write
245                                 operations, the source buffer to write data from.
246 
247   @retval EFI_SUCCESS           The data was read from or written to the PCI root bridge.
248   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
249   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
250 
251 **/
252 EFI_STATUS
253 EFIAPI
PciRootBridgeIoPciRead(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)254 PciRootBridgeIoPciRead (
255   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
256   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
257   IN     UINT64                                 Address,
258   IN     UINTN                                  Count,
259   IN OUT VOID                                   *Buffer
260   )
261 {
262   if (Buffer == NULL) {
263     return EFI_INVALID_PARAMETER;
264   }
265 
266   return PciRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
267 }
268 
269 /**
270   Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
271 
272   @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
273   @param  Width                 Signifies the width of the memory operations.
274   @param  Address               The base address of the memory operations.
275   @param  Count                 The number of memory operations to perform.
276   @param  Buffer                For read operations, the destination buffer to store the results. For write
277                                 operations, the source buffer to write data from.
278 
279   @retval EFI_SUCCESS           The data was read from or written to the PCI root bridge.
280   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
281   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
282 
283 **/
284 EFI_STATUS
285 EFIAPI
PciRootBridgeIoPciWrite(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)286 PciRootBridgeIoPciWrite (
287   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
288   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
289   IN     UINT64                                 Address,
290   IN     UINTN                                  Count,
291   IN OUT VOID                                   *Buffer
292   )
293 {
294   if (Buffer == NULL) {
295     return EFI_INVALID_PARAMETER;
296   }
297 
298   return PciRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
299 }
300