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