1 // 2 // Copyright (c) 2010-2018 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using Antmicro.Renode.Core; 9 using Antmicro.Renode.Core.Structure; 10 using Antmicro.Renode.Logging; 11 using Antmicro.Renode.Peripherals.Bus; 12 13 namespace Antmicro.Renode.Peripherals.PCI 14 { 15 public class VersatilePCI : SimpleContainer<IPCIPeripheral>, IDoubleWordPeripheral 16 { VersatilePCI(IMachine machine)17 public VersatilePCI(IMachine machine) : base(machine) 18 { 19 info = new PCIInfo[4]; 20 _info = new bool[4]; 21 int i; 22 for(i = 0; i < 4; i++) 23 { 24 _info[i] = false; 25 } 26 } 27 Register(IPCIPeripheral peripheral, NumberRegistrationPoint<int> registrationPoint)28 public override void Register(IPCIPeripheral peripheral, NumberRegistrationPoint<int> registrationPoint) 29 { 30 base.Register(peripheral, registrationPoint); 31 info[registrationPoint.Address] = peripheral.GetPCIInfo(); 32 _info[registrationPoint.Address] = true; 33 } 34 35 [ConnectionRegion("config")] ReadDoubleWordConfig(long offset)36 public uint ReadDoubleWordConfig(long offset) 37 { 38 switch(offset) 39 { 40 case 0x0: 41 return 0x030010ee; // DEVICE_ID 42 case 0x8: 43 return 0x0b400000; // CLASS_ID 44 } 45 return 0; 46 } 47 48 [ConnectionRegion("config")] WriteDoubleWordConfig(long offset, uint value)49 public void WriteDoubleWordConfig(long offset, uint value) 50 { 51 } 52 ReadDoubleWord(long offset)53 public virtual uint ReadDoubleWord(long offset) 54 { 55 //if (offset < 0x800) return 0; 56 //offset -= 0x800; 57 int pci_num = (int)(offset / 0x800); 58 if(pci_num > 3) 59 return 0; 60 if(!_info[pci_num]) 61 return 0; 62 PCIInfo linfo = info[pci_num]; 63 offset -= pci_num * 0x800; 64 if(offset == 0x00) 65 return (uint)linfo.vendor_id + (uint)(linfo.device_id << 16); 66 if(offset == 0x04) 67 return (1 << 25) | (1 << 1) | (1 << 0); // cmd ? 68 if(offset == 0x08) 69 return (uint)(linfo.device_class << 16); // class 70 if(offset == 0x0c) 71 return 0x8; // ? 72 if((offset >= 0x10) && (offset < 0x2c)) 73 { 74 uint bar_id = (uint)((offset - 0x10) / 4); 75 return linfo.BAR[bar_id]; 76 } 77 if(offset == 0x2c) 78 return (uint)linfo.sub_vendor_id + (uint)(linfo.sub_device_id << 16); 79 if(offset == 0x30) 80 return 0x1; // rom ? 81 if(offset == 0x3c) 82 return (uint)((0x1 << 8) | (24 + pci_num)); // slot 24 pin 1 (pci0), slot 25 pin 1 (pci1) ... 83 if(offset == 0x34) 84 return 0x1; // ? 85 return 0; 86 } 87 WriteDoubleWord(long offset, uint value)88 public virtual void WriteDoubleWord(long offset, uint value) 89 { 90 //if (offset < 0x800) return; 91 //offset -= 0x800; 92 int pci_num = (int)(offset / 0x800); 93 if(pci_num > 3) 94 return; 95 if(!_info[pci_num]) 96 return; 97 PCIInfo linfo = info[pci_num]; 98 offset -= pci_num * 0x800; 99 if((offset >= 0x10) && (offset < 0x2c)) 100 { 101 uint bar_id = (uint)((offset - 0x10) / 4); 102 if(value == 0xFFFFFFFF) 103 { 104 linfo.BAR[bar_id] = linfo.BAR_len[bar_id]; 105 } 106 else 107 { 108 linfo.BAR[bar_id] = value; 109 } 110 } 111 } 112 113 [ConnectionRegion("io")] WriteDoubleWordIO(long offset, uint value)114 public void WriteDoubleWordIO(long offset, uint value) 115 { 116 this.Log(LogLevel.Noisy, "writeIO {0:X}, value 0x{1:X}", offset, value); 117 118 int found = -1; 119 int bar_no = -1; 120 for(int c = 0; c < 3; c++) 121 { 122 if(!_info[c]) 123 continue; 124 for(int i = 0; i < 8; i++) 125 { 126 if(info[c].BAR_len[i] == 0) 127 continue; 128 if((offset >= (info[c].BAR[i] & 0x0FFFFFFF)) && (offset < ((info[c].BAR[i] & 0xFFFFFFF) + info[c].BAR_len[i]))) 129 { 130 found = c; 131 bar_no = i; 132 break; 133 } 134 } 135 } 136 if(found == -1) 137 return; 138 139 PCIInfo linfo = info[found]; 140 offset -= (linfo.BAR[bar_no] & 0xFFFFFFF); 141 IPCIPeripheral pci_device = GetByAddress(found); 142 pci_device.WriteDoubleWordPCI((uint)bar_no, offset, value); 143 } 144 145 [ConnectionRegion("io")] ReadDoubleWordIO(long offset)146 public uint ReadDoubleWordIO(long offset) 147 { 148 this.Log(LogLevel.Noisy, "readIO {0:X}", offset); 149 150 // (1) search for pci slot and bar no 151 int found = -1; 152 int bar_no = -1; 153 for(int c = 0; c < 3; c++) 154 { 155 if(!_info[c]) 156 continue; 157 for(int i = 0; i < 8; i++) 158 { 159 if(info[c].BAR_len[i] == 0) 160 continue; 161 if((offset >= (info[c].BAR[i] & 0x0FFFFFFF)) && (offset < ((info[c].BAR[i] & 0xFFFFFFF) + info[c].BAR_len[i]))) 162 { 163 found = c; 164 bar_no = i; 165 break; 166 } 167 } 168 } 169 if(found == -1) 170 return 0; 171 172 // (2) forward read 173 PCIInfo linfo = info[found]; 174 offset -= (linfo.BAR[bar_no] & 0xFFFFFFF); 175 IPCIPeripheral pci_device = GetByAddress(found); 176 return pci_device.ReadDoubleWordPCI((uint)bar_no, offset); 177 } 178 Reset()179 public override void Reset() 180 { 181 } 182 //private void TransferData(uint value) 183 //{ 184 // if (!children.Keys.Select (x => x.Number).Contains (slaveAddressForPacket)) 185 //} 186 Update()187 private void Update() 188 { 189 } 190 191 private PCIInfo[] info; 192 bool[] _info; 193 } 194 } 195 196