1 // 2 // Copyright (c) 2010-2023 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.Collections.Generic; 9 using System.Linq; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.Structure; 12 using Antmicro.Renode.Core.Structure.Registers; 13 using Antmicro.Renode.Logging; 14 using Antmicro.Renode.Peripherals.Bus; 15 using Antmicro.Renode.Utilities; 16 17 using Range = Antmicro.Renode.Core.Range; 18 19 namespace Antmicro.Renode.Peripherals.PCI 20 { 21 [AllowedTranslations(AllowedTranslation.WordToDoubleWord | AllowedTranslation.ByteToDoubleWord)] 22 public class PCIHost_Bridge : SimpleContainer<IPCIePeripheral>, IPCIeRouter, IDoubleWordPeripheral, IAbsoluteAddressAware, IKnownSize 23 { PCIHost_Bridge(IMachine machine)24 public PCIHost_Bridge(IMachine machine) : base(machine) 25 { 26 registers = CreateRegisters(); 27 } 28 ReadDoubleWord(long offset)29 public uint ReadDoubleWord(long offset) 30 { 31 var value = registers.Read(offset); 32 return value; 33 } 34 WriteDoubleWord(long offset, uint value)35 public void WriteDoubleWord(long offset, uint value) 36 { 37 registers.Write(offset, value); 38 } 39 SetAbsoluteAddress(ulong address)40 public void SetAbsoluteAddress(ulong address) 41 { 42 // Youngest bit denotes IO/Memory type, second one is reserved 43 currentAccessAbsoluteAddress = address & ~3ul; 44 } 45 Reset()46 public override void Reset() 47 { 48 registers.Reset(); 49 50 address = 0; 51 } 52 RegisterBar(Range range, IPCIePeripheral peripheral, uint bar)53 public void RegisterBar(Range range, IPCIePeripheral peripheral, uint bar) 54 { 55 /* Unimplemented, dummy required by IPCIePeripheral interface */ 56 return; 57 } 58 59 public long Size => 0x10; 60 61 protected struct TargetBar 62 { 63 public IPCIePeripheral TargetPeripheral; 64 public uint BarNumber; 65 } 66 CreateRegisters()67 private DoubleWordRegisterCollection CreateRegisters() 68 { 69 var registersDictionary = new Dictionary<long, DoubleWordRegister> 70 { 71 {(long)Registers.ConfigAddress, new DoubleWordRegister(this) 72 .WithReservedBits(0, 2) 73 .WithValueField(2, 6, out registerNumber, name: "Register Number") 74 .WithValueField(8, 3, out functionNumber, name: "Function Number") 75 .WithValueField(11, 5, out deviceNumber, name: "Device Number") 76 .WithValueField(16, 8, out busNumber, name: "Bus Number") 77 .WithReservedBits(24, 7) 78 .WithFlag(31, out configEnabled, name: "Enable") 79 .WithWriteCallback((_, value) => { address = value; }) 80 }, 81 {(long)Registers.ConfigData, new DoubleWordRegister(this) 82 .WithValueField(0, 32, writeCallback: (_, value) => WriteData((uint)value), 83 valueProviderCallback: _ => ReadData(), name: "CONFIG_DATA") 84 }, 85 }; 86 return new DoubleWordRegisterCollection(this, registersDictionary); 87 } 88 WriteData(uint data)89 private void WriteData(uint data) 90 { 91 if(!configEnabled.Value) 92 { 93 this.Log(LogLevel.Warning, "Writing data to device in unhandled state, value : {0:X}", data); 94 return; 95 } 96 97 if(selectedDevice != null) 98 { 99 selectedDevice.ConfigurationWriteDoubleWord((long)registerNumber.Value*4, data); 100 } 101 else 102 { 103 this.Log(LogLevel.Warning, "Trying to write to unexsiting device. Value: {0:X}", data); 104 } 105 } 106 ReadData()107 private uint ReadData() 108 { 109 if(configEnabled.Value) 110 { 111 if(!ChildCollection.TryGetValue((int)deviceNumber.Value, out selectedDevice)) 112 { 113 this.Log(LogLevel.Warning, "Selected unregistered device number : {0}", deviceNumber.Value); 114 selectedDevice = null; 115 return 0; 116 } 117 //Address is multiplied by 4 cause Read function take offset as argument 118 return selectedDevice.ConfigurationReadDoubleWord((long)registerNumber.Value * 4); 119 } 120 else 121 { 122 this.Log(LogLevel.Warning, "Reading data from device in unhandled state"); 123 } 124 return 0; 125 } 126 127 private readonly DoubleWordRegisterCollection registers; 128 private IFlagRegisterField configEnabled; 129 private IValueRegisterField registerNumber; 130 private IValueRegisterField functionNumber; 131 private IValueRegisterField deviceNumber; 132 private IValueRegisterField busNumber; 133 private IPCIePeripheral selectedDevice; 134 135 private ulong currentAccessAbsoluteAddress; 136 private uint address; 137 138 private enum Registers 139 { 140 ConfigAddress = 0x0, 141 ConfigData = 0x4, 142 } 143 } 144 } 145