1 // 2 // Copyright (c) 2010-2024 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.Extensions; 12 using Antmicro.Renode.Core.Structure; 13 using Antmicro.Renode.Core.Structure.Registers; 14 using Antmicro.Renode.Exceptions; 15 using Antmicro.Renode.Logging; 16 using Antmicro.Renode.Peripherals.Bus; 17 using Antmicro.Renode.Utilities; 18 19 namespace Antmicro.Renode.Peripherals.SD 20 { 21 public class MPFS_SDController : NullRegistrationPointPeripheralContainer<SDCard>, IPeripheralContainer<IPhysicalLayer<byte>, NullRegistrationPoint>, IKnownSize, IDisposable, 22 IDoubleWordPeripheral, IWordPeripheral, IBytePeripheral, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IProvidesRegisterCollection<ByteRegisterCollection> 23 { MPFS_SDController(IMachine machine)24 public MPFS_SDController(IMachine machine) : base(machine) 25 { 26 IRQ = new GPIO(); 27 WakeupIRQ = new GPIO(); 28 sysbus = machine.GetSystemBus(this); 29 irqManager = new InterruptManager<Interrupts>(this); 30 internalBuffer = new Queue<byte>(); 31 32 RegistersCollection = new DoubleWordRegisterCollection(this); 33 ByteRegistersCollection = new ByteRegisterCollection(this); 34 InitializeRegisters(); 35 } 36 ReadDoubleWord(long offset)37 public uint ReadDoubleWord(long offset) 38 { 39 if(RegistersCollection.TryRead(offset, out var result)) 40 { 41 return result; 42 } 43 44 return this.ReadDoubleWordUsingByte(offset); 45 } 46 WriteDoubleWord(long offset, uint value)47 public void WriteDoubleWord(long offset, uint value) 48 { 49 if(RegistersCollection.TryWrite(offset, value)) 50 { 51 return; 52 } 53 54 this.WriteDoubleWordUsingByte(offset, value); 55 } 56 ReadWord(long offset)57 public ushort ReadWord(long offset) 58 { 59 if(ByteRegistersCollection.TryRead(offset, out byte low)) 60 { 61 ushort high = ByteRegistersCollection.Read(offset + 1); 62 return (ushort) ((high << 8) + low); 63 }; 64 65 return this.ReadWordUsingDoubleWord(offset); 66 } 67 WriteWord(long offset, ushort value)68 public void WriteWord(long offset, ushort value) 69 { 70 if(ByteRegistersCollection.TryWrite(offset, (byte) value)) 71 { 72 ByteRegistersCollection.Write(offset+1, (byte) (value >> 8)); 73 return; 74 }; 75 76 this.WriteWordUsingDoubleWord(offset, value); 77 } 78 ReadByte(long offset)79 public byte ReadByte(long offset) 80 { 81 return ByteRegistersCollection.Read(offset); 82 } 83 WriteByte(long offset, byte value)84 public void WriteByte(long offset, byte value) 85 { 86 ByteRegistersCollection.Write(offset, value); 87 } 88 Reset()89 public override void Reset() 90 { 91 RegisteredPeripheral?.Reset(); 92 RegistersCollection.Reset(); 93 irqManager.Reset(); 94 internalBuffer.Clear(); 95 bytesRead = 0; 96 } 97 Dispose()98 public void Dispose() 99 { 100 RegisteredPeripheral?.Dispose(); 101 } 102 GetRegistrationPoints(IPhysicalLayer<byte> peripheral)103 public IEnumerable<NullRegistrationPoint> GetRegistrationPoints(IPhysicalLayer<byte> peripheral) 104 { 105 return (peripheral == phy) 106 ? new[] { NullRegistrationPoint.Instance } 107 : new NullRegistrationPoint[0]; 108 } 109 Register(IPhysicalLayer<byte> peripheral, NullRegistrationPoint registrationPoint)110 public void Register(IPhysicalLayer<byte> peripheral, NullRegistrationPoint registrationPoint) 111 { 112 if(phy != null) 113 { 114 throw new RegistrationException("There is already a PHY registered for this controller"); 115 } 116 phy = peripheral; 117 } 118 Unregister(IPhysicalLayer<byte> peripheral)119 public void Unregister(IPhysicalLayer<byte> peripheral) 120 { 121 if(phy != peripheral) 122 { 123 throw new RegistrationException("Trying to unregister PHY that is currently not registered in this controller"); 124 125 } 126 phy = null; 127 } 128 129 [IrqProvider] 130 public GPIO IRQ { get; private set; } 131 132 public GPIO WakeupIRQ { get; private set; } 133 134 public long Size => 0x2000; 135 136 public DoubleWordRegisterCollection RegistersCollection { get; } 137 public ByteRegisterCollection ByteRegistersCollection { get; } 138 DoubleWordRegisterCollection IProvidesRegisterCollection<DoubleWordRegisterCollection>.RegistersCollection => RegistersCollection; 139 ByteRegisterCollection IProvidesRegisterCollection<ByteRegisterCollection>.RegistersCollection => ByteRegistersCollection; 140 141 IEnumerable<IRegistered<IPhysicalLayer<byte>, NullRegistrationPoint>> IPeripheralContainer<IPhysicalLayer<byte>, NullRegistrationPoint>.Children => phy != null 142 ? new [] { Registered.Create(phy, NullRegistrationPoint.Instance) } 143 : new IRegistered<IPhysicalLayer<byte>, NullRegistrationPoint>[0]; 144 InitializeRegisters()145 private void InitializeRegisters() 146 { 147 var responseFields = new IValueRegisterField[4]; 148 149 Registers.PhySettings_HRS04.Define32(this) 150 .WithValueField(0, 6, out addressField, name: "UHS-I Delay Address Pointer (USI_ADDR)") 151 .WithReservedBits(6, 2) 152 .WithValueField(8, 8, out writeDataField, name: "UHS-I Settings Write Data (UIS_WDATA)") 153 .WithValueField(16, 5, out readDataField, FieldMode.Read, name: "UHS-I Settings Read Data (UIS_RDATA)") 154 .WithReservedBits(21, 3) 155 .WithFlag(24, out var writeRequestFlag, name: "UHS-I Settings Write Request (UIS_WR)") 156 .WithFlag(25, out var readRequestFlag, name: "UHS-I Settings Read Request (UIS_RD)") 157 .WithFlag(26, out ackField, FieldMode.Read, name: "UHS-I Settings Acknowledge (UIS_ACK)") 158 .WithReservedBits(27, 5) 159 .WithWriteCallback((_, value) => 160 { 161 // here we set ack field even when no PHY is registered 162 // this is intentional - the uboot test showed that this field 163 // might be necessary to proceed with booting even when actual 164 // reads/writes to PHY are ignored 165 ackField.Value = (writeRequestFlag.Value || readRequestFlag.Value); 166 167 if(readRequestFlag.Value) 168 { 169 readRequestFlag.Value = false; 170 if(phy == null) 171 { 172 this.Log(LogLevel.Warning, "Trying to read from an unregistered PHY"); 173 } 174 else 175 { 176 readDataField.Value = phy.Read((byte)addressField.Value); 177 } 178 } 179 180 if(writeRequestFlag.Value) 181 { 182 writeRequestFlag.Value = false; 183 if(phy == null) 184 { 185 this.Log(LogLevel.Warning, "Trying to write to an unregistered PHY"); 186 } 187 else 188 { 189 phy.Write((byte)addressField.Value, (byte)writeDataField.Value); 190 } 191 } 192 }) 193 ; 194 195 Registers.BlockSizeBlockCount_SRS01.Define32(this) 196 .WithValueField(0, 12, out blockSizeField, name: "Transfer Block Size (TBS)") 197 .WithValueField(16, 16, out blockCountField, name: "Block Count For Current Transfer (BCCT)") 198 ; 199 200 Registers.Argument1_SRS02.Define32(this) 201 .WithValueField(0, 32, out var commandArgument1Field, name: "Command Argument 1 (ARG1)") 202 ; 203 204 ByteRegisters.CommandTransferMode_SRS03_3.Define8(this) 205 .WithEnumField(0, 6, out commandIndex, name: "Command Index (CI)") 206 .WithReservedBits(6, 2) 207 .WithWriteCallback((_, val) => 208 { 209 var sdCard = RegisteredPeripheral; 210 if(sdCard == null) 211 { 212 this.Log(LogLevel.Warning, "Tried to send a command, but no SD card is currently attached"); 213 return; 214 } 215 216 var commandResult = sdCard.HandleCommand((uint)commandIndex.Value, (uint)commandArgument1Field.Value); 217 var responseType = responseTypeSelectField.Value; 218 switch(responseType) 219 { 220 case ResponseType.NoResponse: 221 if(commandResult.Length != 0) 222 { 223 this.Log(LogLevel.Warning, "Expected no response, but {0} bits received", commandResult.Length); 224 return; 225 } 226 break; 227 case ResponseType.Response136Bits: 228 // our response does not contain 8 bits: 229 // * start bit 230 // * transmission bit 231 // * command index / reserved bits (6 bits) 232 if(commandResult.Length != 128) 233 { 234 this.Log(LogLevel.Warning, "Unexpected a response of length 128 bits (excluding control bits), but {0} received", commandResult.Length); 235 return; 236 } 237 // the following bits are considered a part of returned register, but are not included in the response buffer: 238 // * CRC7 (7 bits) 239 // * end bit 240 // that's why we are skipping the initial 8-bits 241 responseFields[0].Value = commandResult.AsUInt32(8); 242 responseFields[1].Value = commandResult.AsUInt32(40); 243 responseFields[2].Value = commandResult.AsUInt32(72); 244 responseFields[3].Value = commandResult.AsUInt32(104, 24); 245 break; 246 case ResponseType.Response48Bits: 247 case ResponseType.Response48BitsWithBusy: 248 // our response does not contain 16 bits: 249 // * start bit 250 // * transmission bit 251 // * command index / reserved bits (6 bits) 252 // * CRC7 (7 bits) 253 // * end bit 254 if(commandResult.Length != 32) 255 { 256 this.Log(LogLevel.Warning, "Expected a response of length {0} bits (excluding control bits and CRC), but {1} received", 32, commandResult.Length); 257 return; 258 } 259 responseFields[0].Value = commandResult.AsUInt32(); 260 break; 261 default: 262 this.Log(LogLevel.Warning, "Unexpected response type selected: {0}. Ignoring the command response.", responseTypeSelectField.Value); 263 return; 264 } 265 266 ProcessCommand(sdCard, commandIndex.Value); 267 268 irqManager.SetInterrupt(Interrupts.BufferWriteReady, irqManager.IsEnabled(Interrupts.BufferWriteReady)); 269 irqManager.SetInterrupt(Interrupts.BufferReadReady, irqManager.IsEnabled(Interrupts.BufferReadReady)); 270 irqManager.SetInterrupt(Interrupts.CommandComplete, irqManager.IsEnabled(Interrupts.CommandComplete)); 271 if(responseType == ResponseType.Response48BitsWithBusy) 272 { 273 irqManager.SetInterrupt(Interrupts.TransferComplete, irqManager.IsEnabled(Interrupts.TransferComplete)); 274 } 275 }) 276 ; 277 278 ByteRegisters.CommandTransferMode_SRS03_2.Define8(this) 279 .WithEnumField(0, 2, out responseTypeSelectField, name: "Response Type Select (RTS)") 280 .WithReservedBits(2, 1) 281 .WithTag("Command CRC Check Enable (CRCCE)", 3, 1) 282 .WithTag("Command Index Check Enable (CICE)", 4, 1) 283 .WithEnumField(5, 1, out dataPresentSelect, name: "Data Present Select (DPS)") 284 .WithTag("Command Type (CT)", 6, 2) 285 ; 286 287 ByteRegisters.CommandTransferMode_SRS03_1.Define8(this) 288 .WithTag("Response Interrupt Disable (RID)", 0, 1) 289 .WithReservedBits(1, 7) 290 ; 291 292 ByteRegisters.CommandTransferMode_SRS03_0.Define8(this) 293 .WithFlag(0, out isDmaEnabled, name: "DMA Enable") 294 .WithTag("Block Count Enable (BCE)", 1, 1) 295 .WithTag("Auto CMD Enable (ACE)", 2, 2) 296 .WithEnumField(4, 1, out dataTransferDirectionSelect, name: "Data Transfer Direction Select (DTDS)") 297 .WithTag("Multi/Single Block Select (MSBS)", 5, 1) 298 .WithTag("Response Type R1/R5 (RECT)", 6, 1) 299 .WithTag("Response Error Check Enable (RECE)", 7, 1) 300 ; 301 302 Registers.Response1_SRS04.Define32(this) 303 .WithValueField(0, 32, out responseFields[0], FieldMode.Read, name: "Response Register #1 (RESP1)") 304 ; 305 306 Registers.Response2_SRS05.Define32(this) 307 .WithValueField(0, 32, out responseFields[1], FieldMode.Read, name: "Response Register #2 (RESP2)") 308 ; 309 310 Registers.Response3_SRS06.Define32(this) 311 .WithValueField(0, 32, out responseFields[2], FieldMode.Read, name: "Response Register #3 (RESP3)") 312 ; 313 314 Registers.Response4_SRS07.Define32(this) 315 .WithValueField(0, 32, out responseFields[3], FieldMode.Read, name: "Response Register #4 (RESP4)") 316 ; 317 318 Registers.DataBuffer_SRS08.Define32(this).WithValueField(0, 32, name: "Buffer Data Port (BDP)", 319 valueProviderCallback: _ => 320 { 321 var sdCard = RegisteredPeripheral; 322 if(sdCard == null) 323 { 324 this.Log(LogLevel.Warning, "Tried to read data, but no SD card is currently attached"); 325 return 0; 326 } 327 if(isDmaEnabled.Value) 328 { 329 this.Log(LogLevel.Debug, "Reading data in DMA mode from register that does not support it"); 330 } 331 if(!internalBuffer.Any()) 332 { 333 return 0; 334 } 335 return ReadBuffer(); 336 }, 337 writeCallback: (_, value) => 338 { 339 var sdCard = RegisteredPeripheral; 340 if(sdCard == null) 341 { 342 this.Log(LogLevel.Warning, "Tried to write data, but no SD card is currently attached"); 343 return; 344 } 345 if(isDmaEnabled.Value) 346 { 347 this.Log(LogLevel.Warning, "Tried to write data in DMA mode to register that does not support it"); 348 return; 349 } 350 WriteBuffer(sdCard, BitConverter.GetBytes((uint)value)); 351 }) 352 ; 353 354 Registers.PresentState_SRS09.Define32(this) 355 .WithFlag(0, FieldMode.Read, name: "Command Inhibit CMD (CICMD)") 356 .WithFlag(1, FieldMode.Read, name: "Command Inhibit DAT (CIDAT)") // as sending a command is instantienous those two bits will probably always be 0 357 // ... 358 .WithFlag(10, FieldMode.Read, name: "Buffer Write Enable (BWE)", valueProviderCallback: _ => true) 359 .WithFlag(11, FieldMode.Read, name: "Buffer Read Enable (BRE)", valueProviderCallback: _ => RegisteredPeripheral == null ? false : internalBuffer.Any()) 360 .WithFlag(16, FieldMode.Read, name: "Card Inserted (CI)", valueProviderCallback: _ => RegisteredPeripheral != null) 361 .WithFlag(17, FieldMode.Read, name: "Card State Stable (CSS)", valueProviderCallback: _ => true) 362 .WithFlag(18, FieldMode.Read, name: "Card Detect Pin Level (CDSL)", valueProviderCallback: _ => RegisteredPeripheral != null) 363 .WithFlag(20, FieldMode.Read, name: "Line Signal Level (DATSL1 - DAT[0])", valueProviderCallback: _ => true) 364 .WithFlag(21, FieldMode.Read, name: "Line Signal Level (DATSL1 - DAT[1])", valueProviderCallback: _ => true) 365 .WithFlag(22, FieldMode.Read, name: "Line Signal Level (DATSL1 - DAT[2])", valueProviderCallback: _ => true) 366 .WithFlag(23, FieldMode.Read, name: "Line Signal Level (DATSL1 - DAT[3])", valueProviderCallback: _ => true) 367 ; 368 369 Registers.HostControl2_SRS11.Define32(this) 370 .WithFlag(1, FieldMode.Read, name: "Internal Clock Stable (ICS)", valueProviderCallback: _ => true) 371 .WithTag("Software Reset For CMD Line (SRCMD)", 25, 1) 372 .WithTag("Software Reset For DAT Line (SRDAT)", 26, 1) 373 ; 374 375 Registers.ErrorNormalInterruptStatus_SRS12.Bind(this, irqManager.GetRegister<DoubleWordRegister>( 376 valueProviderCallback: (irq, _) => irqManager.IsSet(irq), 377 writeCallback: (irq, prev, curr) => { if(curr) irqManager.ClearInterrupt(irq); } )) 378 ; 379 380 Registers.ErrorNormalStatusEnable_SRS13.Bind(this, irqManager.GetRegister<DoubleWordRegister>( 381 valueProviderCallback: (irq, _) => irqManager.IsEnabled(irq), 382 writeCallback: (irq, _, curr) => 383 { 384 if(curr) 385 { 386 irqManager.EnableInterrupt(irq, curr); 387 } 388 else 389 { 390 irqManager.DisableInterrupt(irq); 391 } 392 })) 393 ; 394 395 Registers.Capabilities1_SRS16.Define32(this) 396 // these fields must return non-zero values in order for u-boot to boot 397 .WithValueField(0, 6, FieldMode.Read, valueProviderCallback: _ => 4, name: "Timeout clock frequency (TCS)") 398 .WithFlag(7, FieldMode.Read, valueProviderCallback: _ => true, name: "Timeout clock unit (TCU)") 399 .WithValueField(8, 8, FieldMode.Read, valueProviderCallback: _ => 1, name: "Base Clock Frequency For SD Clock (BCSDCLK)") 400 .WithFlag(19, FieldMode.Read, valueProviderCallback: _ => false, name: "ADMA1 Support") 401 .WithFlag(22, FieldMode.Read, valueProviderCallback: _ => true, name: "SDMA Support") 402 .WithFlag(24, FieldMode.Read, valueProviderCallback: _ => true, name: "Voltage Support 3.3V (VS33)") 403 .WithFlag(25, FieldMode.Read, valueProviderCallback: _ => true, name: "Voltage Support 3.0V (VS30)") 404 .WithFlag(26, FieldMode.Read, valueProviderCallback: _ => true, name: "Voltage Support 1.8V (VS18)") 405 .WithFlag(28, FieldMode.Read, valueProviderCallback: _ => true, name: "64-bit DMA Support") 406 ; 407 Registers.SDMASystemAddressArgument2_SRS00.Define32(this) 408 .WithValueField(0, 32, name: "SDMA Address", 409 valueProviderCallback: _ => 410 { 411 if(dmaSystemAddressHigh.Value != 0) 412 { 413 this.Log(LogLevel.Warning, "DMA System address 2 is nonzero: {0} ", dmaSystemAddressHigh.Value); 414 } 415 return dmaSystemAddressLow.Value; 416 }, 417 writeCallback: (_, val) => 418 { 419 dmaSystemAddressHigh.Value = 0; 420 dmaSystemAddressLow.Value = val; 421 } 422 ) 423 424 ; 425 426 Registers.DmaSystemAddressLow_SRS22.Define32(this) 427 .WithValueField(0, 32, out dmaSystemAddressLow, name: "ADMA/SDMA System Address 1") 428 ; 429 430 Registers.DmaSystemAddressHigh_SRS23.Define32(this) 431 .WithValueField(0, 32, out dmaSystemAddressHigh, name: "ADMA/SDMA System Address 2") 432 ; 433 } 434 ProcessCommand(SDCard sdCard, SDCardCommand command)435 private void ProcessCommand(SDCard sdCard, SDCardCommand command) 436 { 437 switch(command) 438 { 439 case SDCardCommand.CheckSwitchableFunction: 440 internalBuffer.EnqueueRange(sdCard.ReadSwitchFunctionStatusRegister()); 441 return; 442 case SDCardCommand.SendInterfaceConditionCommand: 443 internalBuffer.EnqueueRange(sdCard.ReadExtendedCardSpecificDataRegister()); 444 return; 445 } 446 447 // early exit if no data is present 448 if(dataPresentSelect.Value != DataPresentSelect.DataPresent) 449 { 450 return; 451 } 452 453 var bytesCount = (uint)(blockCountField.Value * blockSizeField.Value); 454 switch(dataTransferDirectionSelect.Value) 455 { 456 case DataTransferDirectionSelect.Read: 457 ReadCard(sdCard, bytesCount); 458 break; 459 case DataTransferDirectionSelect.Write: 460 WriteCard(sdCard, bytesCount); 461 break; 462 default: 463 this.Log(LogLevel.Warning, "Invalid data transfer direction {};", dataTransferDirectionSelect.Value); 464 break; 465 } 466 } 467 ReadCard(SDCard sdCard, uint size)468 private void ReadCard(SDCard sdCard, uint size) 469 { 470 var data = sdCard.ReadData(size); 471 if(isDmaEnabled.Value) 472 { 473 internalBuffer.Clear(); 474 bytesRead = 0; 475 sysbus.WriteBytes(data, ((ulong)dmaSystemAddressHigh.Value << 32) | dmaSystemAddressLow.Value); 476 Machine.LocalTimeSource.ExecuteInNearestSyncedState(_ => 477 { 478 irqManager.SetInterrupt(Interrupts.TransferComplete, irqManager.IsEnabled(Interrupts.TransferComplete)); 479 }); 480 } 481 internalBuffer.EnqueueRange(data); 482 } 483 WriteBuffer(SDCard sdCard, byte[] data)484 private void WriteBuffer(SDCard sdCard, byte[] data) 485 { 486 var limit = (uint)(blockCountField.Value * blockSizeField.Value); 487 internalBuffer.EnqueueRange(data); 488 if(internalBuffer.Count < limit) 489 { 490 return; 491 } 492 sdCard.WriteData(internalBuffer.DequeueAll()); 493 irqManager.SetInterrupt(Interrupts.TransferComplete, irqManager.IsEnabled(Interrupts.TransferComplete)); 494 } 495 WriteCard(SDCard sdCard, uint size)496 private void WriteCard(SDCard sdCard, uint size) 497 { 498 var bytes = new byte[size]; 499 if(isDmaEnabled.Value) 500 { 501 bytes = sysbus.ReadBytes(((ulong)dmaSystemAddressHigh.Value << 32) | dmaSystemAddressLow.Value, (int)size); 502 } 503 else 504 { 505 if(internalBuffer.Count < size) 506 { 507 this.Log(LogLevel.Warning, "Could not write {0} bytes to SD card, writing {1} bytes instead.", size, internalBuffer.Count); 508 size = (uint)internalBuffer.Count; 509 } 510 bytes = internalBuffer.DequeueRange((int)size); 511 } 512 sdCard.WriteData(bytes); 513 Machine.LocalTimeSource.ExecuteInNearestSyncedState(_ => 514 { 515 irqManager.SetInterrupt(Interrupts.TransferComplete, irqManager.IsEnabled(Interrupts.TransferComplete)); 516 }); 517 } 518 ReadBuffer()519 private uint ReadBuffer() 520 { 521 var internalBytes = internalBuffer.DequeueRange(4); 522 bytesRead += (uint)internalBytes.Length; 523 irqManager.SetInterrupt(Interrupts.BufferReadReady, irqManager.IsEnabled(Interrupts.BufferReadReady)); 524 if(bytesRead >= (blockCountField.Value * blockSizeField.Value) || !internalBuffer.Any()) 525 { 526 irqManager.SetInterrupt(Interrupts.TransferComplete, irqManager.IsEnabled(Interrupts.TransferComplete)); 527 bytesRead = 0; 528 // If we have read the exact amount of data we wanted, we can clear the buffer from any leftovers. 529 internalBuffer.Clear(); 530 } 531 return internalBytes.ToUInt32Smart(); 532 } 533 534 private IFlagRegisterField ackField; 535 private IFlagRegisterField isDmaEnabled; 536 private IValueRegisterField blockSizeField; 537 private IValueRegisterField blockCountField; 538 private IValueRegisterField addressField; 539 private IValueRegisterField readDataField; 540 private IValueRegisterField writeDataField; 541 private IValueRegisterField dmaSystemAddressLow; 542 private IValueRegisterField dmaSystemAddressHigh; 543 private IEnumRegisterField<DataPresentSelect> dataPresentSelect; 544 private IEnumRegisterField<DataTransferDirectionSelect> dataTransferDirectionSelect; 545 private IEnumRegisterField<SDCardCommand> commandIndex; 546 private IEnumRegisterField<ResponseType> responseTypeSelectField; 547 548 private uint bytesRead; 549 private IPhysicalLayer<byte> phy; 550 private Queue<byte> internalBuffer; 551 552 private readonly IBusController sysbus; 553 private readonly InterruptManager<Interrupts> irqManager; 554 555 private enum Registers 556 { 557 GeneralInformation_HRS00 = 0x000, 558 DebounceSetting_HRS01 = 0x004, 559 BusSetting_HRS02 = 0x008, 560 AXIEErrorResponses_HRS03 = 0x00C, 561 PhySettings_HRS04 = 0x10, 562 EMMCControl_HRS06 = 0x18, 563 IODelayInformation_HRS07 = 0x01C, 564 HostCapability_HRS30 = 0x078, 565 HostControllerVersion_HRS31 = 0x07C, 566 FSMMonitor_HRS32 = 0x080, 567 TuneStatus0_HRS33 = 0x084, 568 TuneStatus1_HRS34 = 0x088, 569 TuneDebug_HRS35 = 0x08C, 570 BootStatus_HRS36 = 0x090, 571 ReadBlockGapCoefficientInterfaceModeSelect_HRS37 = 0x094, 572 ReadBlockGapCoefficient_HRS38 = 0x098, 573 HostControllerVersion_SlotInterruptStatus_CRS63 = 0x0FC, 574 SDMASystemAddressArgument2_SRS00 = 0x200, 575 BlockSizeBlockCount_SRS01 = 0x204, 576 Argument1_SRS02 = 0x208, 577 CommandTransferMode_SRS03 = 0x20C, 578 Response1_SRS04 = 0x210, 579 Response2_SRS05 = 0x214, 580 Response3_SRS06 = 0x218, 581 Response4_SRS07 = 0x21C, 582 DataBuffer_SRS08 = 0x220, 583 PresentState_SRS09 = 0x224, 584 HostControl1_SRS10 = 0x228, 585 HostControl2_SRS11 = 0x22C, 586 ErrorNormalInterruptStatus_SRS12 = 0x230, 587 ErrorNormalStatusEnable_SRS13 = 0x234, 588 ErrorNormalSignalEnable_SRS14 = 0x238, 589 HostControl2_SRS15 = 0x23C, 590 Capabilities1_SRS16 = 0x240, 591 Capabilities2_SRS17 = 0x244, 592 Capabilities3_SRS18 = 0x248, 593 Capabilities4_SRS19 = 0x24C, 594 ForceEvent_SRS20 = 0x250, 595 ADMAErrorStatus_SRS21 = 0x254, 596 DmaSystemAddressLow_SRS22 = 0x258, 597 DmaSystemAddressHigh_SRS23 = 0x25C, 598 PresetValue_DefaultSpeed_SRS24 = 0x260, 599 PresetValue_HighSpeedAndSDR12_SRS25 = 0x264, 600 PresetValue_SDR25AndSDR50_SRS26 = 0x268, 601 PresetValue_SDR104AndDDR50_SRS27 = 0x26C, 602 PresetValue_UHSII_SRS29 = 0x274, 603 CommandQueuingVersion_CQRS00 = 0x400, 604 CommandQueuingCapabilities_CQRS01 = 0x404, 605 CommandQueuingConfiguration_CQRS02 = 0x408, 606 CommandQueuingControl_CQRS03 = 0x40C, 607 CommandQueuingInterruptStatus_CQRS04 = 0x410, 608 CommandQueuingInterruptStatusEnable_CQRS05 = 0x414, 609 CommandQueuingInterruptSignalEnable_CQRS06 = 0x418, 610 InterruptCoalescing_CQRS07 = 0x41C, 611 CommandQueuingTaskDescriptorListBaseAddress_CQRS08 = 0x420, 612 CommandQueuingTaskDescriptorListBaseAddressUpper32Bits_CQRS09 = 0x424, 613 CommandQueuingTaskDoorbell_CQRS10 = 0x428, 614 TaskCompleteNotification_CQRS11 = 0x42C, 615 DeviceQueueStatus_CQRS12 = 0x430, 616 DevicePendingTasks_CQRS13 = 0x434, 617 TaskClear_CQRS14 = 0x438, 618 SendStatusConfiguration1_CQRS16 = 0x440, 619 SendStatusConfiguration2_CQRS17 = 0x444, 620 CommandResponseForDirect_CommandTask_CQRS18 = 0x448, 621 ResponseModeErrorMask_CQRS20 = 0x450, 622 TaskErrorInformation_CQRS21 = 0x454, 623 CommandResponseIndex_CQRS22 = 0x458, 624 CommandResponseArgument_CQRS23 = 0x45C 625 } 626 627 private enum ByteRegisters { 628 CommandTransferMode_SRS03_0 = 0x20C, 629 CommandTransferMode_SRS03_1 = 0x20D, 630 CommandTransferMode_SRS03_2 = 0x20E, 631 CommandTransferMode_SRS03_3 = 0x20F 632 } 633 634 private enum DataPresentSelect 635 { 636 NoDataPresent = 0, 637 DataPresent = 1 638 } 639 640 private enum DataTransferDirectionSelect 641 { 642 Write = 0, 643 Read = 1 644 } 645 646 private enum ResponseType 647 { 648 NoResponse = 0, 649 Response136Bits = 1, 650 Response48Bits = 2, 651 Response48BitsWithBusy = 3 652 } 653 654 private enum Interrupts 655 { 656 CommandComplete = 0, 657 TransferComplete = 1, 658 BlockGapEvent = 2, 659 DMAInterrupt = 3, 660 BufferWriteReady = 4, 661 BufferReadReady = 5, 662 CardIsertion = 6, 663 CardRemoval = 7, 664 CardInterrupt = 8, 665 // [13:9] Reserved 666 QueuingEnabledInterrupt = 14, 667 ErrorInterrupt = 15, 668 CommandTimeoutError = 16, 669 CommandCRCError = 17, 670 CommandEndBitError = 18, 671 CommandIndexError = 19, 672 DataTimeoutError = 20, 673 DataCRCError = 21, 674 DataEndBitError = 22, 675 CurrentLimitError = 23, 676 AutoCMDError = 24, 677 ADMAError = 25, 678 // [26] Reserved 679 ResponseError = 27, 680 // [31:28] Reserved 681 } 682 683 private enum SDCardCommand 684 { 685 CheckSwitchableFunction = 6, 686 SendInterfaceConditionCommand = 8, 687 ReadSingleBlock = 17, 688 ReadMultipleBlocks = 18, 689 WriteSingleBlock = 24, 690 WriteMultipleBlocks = 25, 691 } 692 } 693 } 694