STATIC EFI_STATUS CpuIoMemRW ( IN EFI_CPU_IO_PROTOCOL_WIDTH Width, IN UINTN Count, IN BOOLEAN DestinationStrideFlag, OUT PTR Destination, IN BOOLEAN SourceStrideFlag, IN PTR Source ) /*++ Routine Description: Private service to perform memory mapped I/O read/write Arguments: Width - Width of the memory mapped I/O operation Count - Count of the number of accesses to perform DestinationStrideFlag - Boolean flag indicates if the destination is to be incremented Destination - Destination of the memory mapped I/O operation SourceStrideFlag - Boolean flag indicates if the source is to be incremented Source - Source of the memory mapped I/O operation Returns: EFI_SUCCESS - Successful operation EFI_INVALID_PARAMETER - Width is invalid --*/ { UINTN Stride; UINTN DestinationStride; UINTN SourceStride; Width = Width & 0x03; Stride = (UINTN)1 << Width; DestinationStride = DestinationStrideFlag ? Stride : 0; SourceStride = SourceStrideFlag ? Stride : 0; // // Loop for each iteration and move the data // switch (Width) { case EfiCpuIoWidthUint8: for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) { MEMORY_FENCE (); *Destination.ui8 = *Source.ui8; MEMORY_FENCE (); } break; case EfiCpuIoWidthUint16: for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) { MEMORY_FENCE (); *Destination.ui16 = *Source.ui16; MEMORY_FENCE (); } break; case EfiCpuIoWidthUint32: for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) { MEMORY_FENCE (); *Destination.ui32 = *Source.ui32; MEMORY_FENCE (); } break; case EfiCpuIoWidthUint64: for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) { MEMORY_FENCE (); *Destination.ui64 = *Source.ui64; MEMORY_FENCE (); } break; default: return EFI_INVALID_PARAMETER; } return EFI_SUCCESS; }
EFI_STATUS PcatRootBridgeIoIoRead ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 UserAddress, IN UINTN Count, IN OUT VOID *UserBuffer ) { PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; UINTN InStride; UINTN OutStride; UINTN AlignMask; UINTN Address; PTR Buffer; UINT16 Data16; UINT32 Data32; if ( UserBuffer == NULL ) { return EFI_INVALID_PARAMETER; } PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); Address = (UINTN) UserAddress; Buffer.buf = (UINT8 *)UserBuffer; if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) { return EFI_INVALID_PARAMETER; } if ((UINT32)Width >= EfiPciWidthMaximum) { return EFI_INVALID_PARAMETER; } if ((Width & 0x03) == EfiPciWidthUint64) { return EFI_INVALID_PARAMETER; } AlignMask = (1 << (Width & 0x03)) - 1; if ( Address & AlignMask ) { return EFI_INVALID_PARAMETER; } InStride = 1 << (Width & 0x03); OutStride = InStride; if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) { InStride = 0; } if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) { OutStride = 0; } Width = Width & 0x03; Address += PrivateData->PhysicalIoBase; // // Loop for each iteration and move the data // switch (Width) { case EfiPciWidthUint8: for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) { MEMORY_FENCE(); *Buffer.ui8 = PORT_TO_MEM8(Address); MEMORY_FENCE(); } break; case EfiPciWidthUint16: for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) { MEMORY_FENCE(); if (Buffer.ui & 0x1) { Data16 = PORT_TO_MEM16(Address); *Buffer.ui8 = (UINT8)(Data16 & 0xff); *(Buffer.ui8+1) = (UINT8)((Data16 >> 8) & 0xff); } else { *Buffer.ui16 = PORT_TO_MEM16(Address); } MEMORY_FENCE(); }
EFI_STATUS CpuIoMemRW ( IN EFI_CPU_IO_PROTOCOL_WIDTH Width, IN UINTN Count, IN BOOLEAN InStrideFlag, IN PTR In, IN BOOLEAN OutStrideFlag, OUT PTR Out ) /*++ Routine Description: Private service to provide the memory read/write Arguments: Width of the Memory Access Count of the number of accesses to perform Returns: Status EFI_SUCCESS - Successful transaction EFI_INVALID_PARAMETER - Unsupported width and address combination --*/ // TODO: InStrideFlag - add argument and description to function comment // TODO: In - add argument and description to function comment // TODO: OutStrideFlag - add argument and description to function comment // TODO: Out - add argument and description to function comment { UINTN Stride; UINTN InStride; UINTN OutStride; LONG ReturnedLength; Width = Width & 0x03; Stride = 1 << Width; InStride = InStrideFlag ? Stride : 0; OutStride = OutStrideFlag ? Stride : 0; // // Loop for each iteration and move the data // switch (Width) { case EfiCpuIoWidthUint8: for (; Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { MEMORY_FENCE (); gWinNtThunk->DeviceIoControl ( gDeviceHandle, // Handle to device IOCTL_MEM_COPY, // IO Control code to use Out.ui8, // Out Buffer to communicate to driver Count, // Length of buffer in bytes. In.ui8, // In Buffer to fill in by kernel driver. Count, // Length of buffer in bytes. &ReturnedLength, // Bytes placed in In buffer. NULL // NULL means wait till op. completes. ); MEMORY_FENCE (); } break; case EfiCpuIoWidthUint16: for (; Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { MEMORY_FENCE (); gWinNtThunk->DeviceIoControl ( gDeviceHandle, // Handle to device IOCTL_MEM_COPY, // IO Control code to use Out.ui16, // Out Buffer to communicate to driver Count * 2, // Length of buffer in bytes. In.ui16, // In Buffer to fill in by kernel driver. Count * 2, // Length of buffer in bytes. &ReturnedLength, // Bytes placed in In buffer. NULL // NULL means wait till op. completes. ); MEMORY_FENCE (); } break; case EfiCpuIoWidthUint32: for (; Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { MEMORY_FENCE (); gWinNtThunk->DeviceIoControl ( gDeviceHandle, // Handle to device IOCTL_MEM_COPY, // IO Control code to use Out.ui32, // Out Buffer to communicate to driver Count * 4, // Length of buffer in bytes. In.ui32, // In Buffer to fill in by kernel driver. Count * 4, // Length of buffer in bytes. &ReturnedLength, // Bytes placed in In buffer. NULL // NULL means wait till op. completes. ); MEMORY_FENCE (); } break; default: return EFI_INVALID_PARAMETER; } return EFI_SUCCESS; }