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 
46   Width     = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
47   Stride    = (UINTN)1 << Width;
48   InStride  = InStrideFlag  ? Stride : 0;
49   OutStride = OutStrideFlag ? Stride : 0;
50 
51   //
52   // Loop for each iteration and move the data
53   //
54   switch (Width) {
55   case EfiPciWidthUint8:
56     for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
57       *In.ui8 = *Out.ui8;
58     }
59     break;
60   case EfiPciWidthUint16:
61     for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
62       *In.ui16 = *Out.ui16;
63     }
64     break;
65   case EfiPciWidthUint32:
66     for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
67       *In.ui32 = *Out.ui32;
68     }
69     break;
70   default:
71     return EFI_INVALID_PARAMETER;
72   }
73 
74   return EFI_SUCCESS;
75 }
76 
77 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)78 PciRootBridgeIoPciRW (
79   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
80   IN BOOLEAN                                Write,
81   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
82   IN UINT64                                 UserAddress,
83   IN UINTN                                  Count,
84   IN OUT VOID                               *UserBuffer
85   )
86 {
87   return EFI_SUCCESS;
88 }
89 
90 /**
91   Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
92 
93   @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
94   @param  Width                 Signifies the width of the memory operations.
95   @param  Address               The base address of the memory operations.
96   @param  Count                 The number of memory operations to perform.
97   @param  Buffer                For read operations, the destination buffer to store the results. For write
98                                 operations, the source buffer to write data from.
99 
100   @retval EFI_SUCCESS           The data was read from or written to the PCI root bridge.
101   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
102   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
103 
104 **/
105 EFI_STATUS
106 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)107 PciRootBridgeIoMemRead (
108   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
109   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
110   IN     UINT64                                 Address,
111   IN     UINTN                                  Count,
112   IN OUT VOID                                   *Buffer
113   )
114 {
115   PCI_ROOT_BRIDGE   *Private;
116   UINTN             AlignMask;
117   PTR               In;
118   PTR               Out;
119 
120   if ( Buffer == NULL ) {
121     return EFI_INVALID_PARAMETER;
122   }
123 
124   Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
125 
126   if (!PciRootBridgeMemAddressValid (Private, Address)) {
127     return EFI_INVALID_PARAMETER;
128   }
129 
130   AlignMask = (1 << (Width & 0x03)) - 1;
131   if (Address & AlignMask) {
132     return EFI_INVALID_PARAMETER;
133   }
134 
135   In.buf  = Buffer;
136   Out.buf = (VOID *)(UINTN) Address;
137 
138   switch (Width) {
139   case EfiPciWidthUint8:
140   case EfiPciWidthUint16:
141   case EfiPciWidthUint32:
142   case EfiPciWidthUint64:
143     return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
144 
145   case EfiPciWidthFifoUint8:
146   case EfiPciWidthFifoUint16:
147   case EfiPciWidthFifoUint32:
148   case EfiPciWidthFifoUint64:
149     return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
150 
151   case EfiPciWidthFillUint8:
152   case EfiPciWidthFillUint16:
153   case EfiPciWidthFillUint32:
154   case EfiPciWidthFillUint64:
155     return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
156 
157   default:
158     break;
159   }
160 
161   return EFI_INVALID_PARAMETER;
162 }
163 
164 
165 
166 /**
167   Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
168 
169   @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
170   @param  Width                 Signifies the width of the memory operations.
171   @param  Address               The base address of the memory operations.
172   @param  Count                 The number of memory operations to perform.
173   @param  Buffer                For read operations, the destination buffer to store the results. For write
174                                 operations, the source buffer to write data from.
175 
176   @retval EFI_SUCCESS           The data was read from or written to the PCI root bridge.
177   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
178   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
179 
180 **/
181 EFI_STATUS
182 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)183 PciRootBridgeIoMemWrite (
184   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
185   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
186   IN     UINT64                                 Address,
187   IN     UINTN                                  Count,
188   IN OUT VOID                                   *Buffer
189   )
190 {
191   PCI_ROOT_BRIDGE *Private;
192   UINTN  AlignMask;
193   PTR    In;
194   PTR    Out;
195 
196   if ( Buffer == NULL ) {
197     return EFI_INVALID_PARAMETER;
198   }
199 
200   Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
201 
202   if (!PciRootBridgeMemAddressValid (Private, Address)) {
203     return EFI_INVALID_PARAMETER;
204   }
205 
206   AlignMask = (1 << (Width & 0x03)) - 1;
207   if (Address & AlignMask) {
208     return EFI_INVALID_PARAMETER;
209   }
210 
211   In.buf  = (VOID *)(UINTN) Address;
212   Out.buf = Buffer;
213 
214   switch (Width) {
215   case EfiPciWidthUint8:
216   case EfiPciWidthUint16:
217   case EfiPciWidthUint32:
218   case EfiPciWidthUint64:
219     return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
220 
221   case EfiPciWidthFifoUint8:
222   case EfiPciWidthFifoUint16:
223   case EfiPciWidthFifoUint32:
224   case EfiPciWidthFifoUint64:
225     return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
226 
227   case EfiPciWidthFillUint8:
228   case EfiPciWidthFillUint16:
229   case EfiPciWidthFillUint32:
230   case EfiPciWidthFillUint64:
231     return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
232 
233   default:
234     break;
235   }
236 
237   return EFI_INVALID_PARAMETER;
238 }
239 
240 /**
241   Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
242 
243   @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
244   @param  Width                 Signifies the width of the memory operations.
245   @param  Address               The base address of the memory operations.
246   @param  Count                 The number of memory operations to perform.
247   @param  Buffer                For read operations, the destination buffer to store the results. For write
248                                 operations, the source buffer to write data from.
249 
250   @retval EFI_SUCCESS           The data was read from or written to the PCI root bridge.
251   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
252   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
253 
254 **/
255 EFI_STATUS
256 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)257 PciRootBridgeIoPciRead (
258   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
259   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
260   IN     UINT64                                 Address,
261   IN     UINTN                                  Count,
262   IN OUT VOID                                   *Buffer
263   )
264 {
265   if (Buffer == NULL) {
266     return EFI_INVALID_PARAMETER;
267   }
268 
269   return PciRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
270 }
271 
272 
273 
274 /**
275   Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
276 
277   @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
278   @param  Width                 Signifies the width of the memory operations.
279   @param  Address               The base address of the memory operations.
280   @param  Count                 The number of memory operations to perform.
281   @param  Buffer                For read operations, the destination buffer to store the results. For write
282                                 operations, the source buffer to write data from.
283 
284   @retval EFI_SUCCESS           The data was read from or written to the PCI root bridge.
285   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
286   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
287 
288 **/
289 EFI_STATUS
290 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)291 PciRootBridgeIoPciWrite (
292   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
293   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
294   IN     UINT64                                 Address,
295   IN     UINTN                                  Count,
296   IN OUT VOID                                   *Buffer
297   )
298 {
299   if (Buffer == NULL) {
300     return EFI_INVALID_PARAMETER;
301   }
302 
303   return PciRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
304 }
305 
306 
307