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 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 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 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 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 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 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 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