1 // 2 // Copyright (c) 2010-2024 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 System; 9 using System.Collections.Generic; 10 using System.IO; 11 using System.Linq; 12 using Antmicro.Renode.Exceptions; 13 using Antmicro.Renode.Logging; 14 using Antmicro.Renode.Peripherals.SPI; 15 using Antmicro.Renode.Storage; 16 using Antmicro.Renode.Utilities; 17 using static Antmicro.Renode.Utilities.BitHelper; 18 19 namespace Antmicro.Renode.Peripherals.SD 20 { 21 // Features NOT supported: 22 // * Toggling selected state 23 // * RCA (relative card address) filtering 24 // As a result any SD controller with more than one SD card attached at the same time might not work properly. 25 // Card type (SC/HC/XC/UC) is determined based on the provided capacity 26 public class SDCard : ISPIPeripheral, IDisposable 27 { SDCard(long capacity, bool spiMode = false, BlockLength blockSize = BlockLength.Undefined)28 public SDCard(long capacity, bool spiMode = false, BlockLength blockSize = BlockLength.Undefined) 29 : this(DataStorage.CreateInMemory((int)capacity), capacity, spiMode, blockSize) {} 30 SDCard(string imageFile, long capacity, bool persistent = false, bool spiMode = false, BlockLength blockSize = BlockLength.Undefined)31 public SDCard(string imageFile, long capacity, bool persistent = false, bool spiMode = false, BlockLength blockSize = BlockLength.Undefined) 32 : this(DataStorage.CreateFromFile(imageFile, capacity, persistent), capacity, spiMode, blockSize) {} 33 SDCard(Stream dataBackend, long capacity, bool spiMode = false, BlockLength blockSize = BlockLength.Undefined)34 private SDCard(Stream dataBackend, long capacity, bool spiMode = false, BlockLength blockSize = BlockLength.Undefined) 35 { 36 var blockLenghtInBytes = SDHelpers.BlockLengthInBytes(blockSize); 37 if((blockSize != BlockLength.Undefined) && (capacity % blockLenghtInBytes != 0)) 38 { 39 throw new ConstructionException($"Size (0x{capacity:X}) is not aligned to selected block size(0x{blockLenghtInBytes:X})"); 40 } 41 42 this.spiMode = spiMode; 43 this.highCapacityMode = SDHelpers.TypeFromCapacity((ulong)capacity) != CardType.StandardCapacity_SC; 44 this.capacity = capacity; 45 this.blockSize = blockSize; 46 spiContext = new SpiContext(); 47 48 this.dataBackend = dataBackend; 49 50 var sdCapacityParameters = SDHelpers.SeekForCapacityParameters(capacity, blockSize); 51 blockLengthInBytes = SDHelpers.BlockLengthInBytes(sdCapacityParameters.BlockSize); 52 53 cardStatusGenerator = new VariableLengthValue(32) 54 .DefineFragment(5, 1, () => (treatNextCommandAsAppCommand ? 1 : 0u), name: "APP_CMD bit") 55 .DefineFragment(8, 1, 1, name: "READY_FOR_DATA bit") 56 .DefineFragment(9, 4, () => (uint)state, name: "CURRENT_STATE") 57 ; 58 59 operatingConditionsGenerator = new VariableLengthValue(32) 60 .DefineFragment(7, 1, 1, name: "Reserved for Low Voltage Range") 61 .DefineFragment(8, 1, 1, name: "VDD voltage window 2.0 - 2.1") 62 .DefineFragment(9, 1, 1, name: "VDD voltage window 2.1 - 2.2") 63 .DefineFragment(10, 1, 1, name: "VDD voltage window 2.2 - 2.3") 64 .DefineFragment(11, 1, 1, name: "VDD voltage window 2.3 - 2.4") 65 .DefineFragment(12, 1, 1, name: "VDD voltage window 2.4 - 2.5") 66 .DefineFragment(13, 1, 1, name: "VDD voltage window 2.5 - 2.6") 67 .DefineFragment(14, 1, 1, name: "VDD voltage window 2.6 - 2.7") 68 .DefineFragment(15, 1, 1, name: "VDD voltage window 2.7 - 2.8") 69 .DefineFragment(16, 1, 1, name: "VDD voltage window 2.8 - 2.9") 70 .DefineFragment(17, 1, 1, name: "VDD voltage window 2.9 - 3.0") 71 .DefineFragment(18, 1, 1, name: "VDD voltage window 3.0 - 3.1") 72 .DefineFragment(19, 1, 1, name: "VDD voltage window 3.1 - 3.2") 73 .DefineFragment(20, 1, 1, name: "VDD voltage window 3.2 - 3.3") 74 .DefineFragment(21, 1, 1, name: "VDD voltage window 3.3 - 3.4") 75 .DefineFragment(22, 1, 1, name: "VDD voltage window 3.4 - 3.5") 76 .DefineFragment(23, 1, 1, name: "VDD voltage window 3.5 - 3.6") 77 .DefineFragment(30, 1, () => this.highCapacityMode ? 1 : 0u, name: "Card Capacity Status") 78 .DefineFragment(31, 1, 1, name: "Card power up status bit (busy)") 79 ; 80 81 if(!highCapacityMode) 82 { 83 cardSpecificDataGenerator = new VariableLengthValue(128) 84 .DefineFragment(22, 4, (ulong)sdCapacityParameters.BlockSize, name: "max write data block length") 85 .DefineFragment(47, 3, (uint)sdCapacityParameters.Multiplier, name: "device size multiplier") 86 .DefineFragment(62, 12, (ulong)sdCapacityParameters.DeviceSize, name: "device size") 87 .DefineFragment(80, 4, (uint)sdCapacityParameters.BlockSize, name: "max read data block length") 88 .DefineFragment(84, 12, (uint)( 89 CardCommandClass.Class0 90 | CardCommandClass.Class2 91 | CardCommandClass.Class4 92 ), name: "card command classes") 93 .DefineFragment(96, 3, (uint)TransferRate.Transfer10Mbit, name: "transfer rate unit") 94 .DefineFragment(99, 4, (uint)TransferMultiplier.Multiplier2_5, name: "transfer multiplier") 95 .DefineFragment(126, 2, (uint)CSD.Version1, name: "CSD structure") 96 ; 97 } 98 else 99 { 100 cardSpecificDataGenerator = new VariableLengthValue(128) 101 .DefineFragment(22, 4, (ulong)sdCapacityParameters.BlockSize, name: "max write data block length") 102 .DefineFragment(48, 22, (ulong)sdCapacityParameters.DeviceSize, name: "device size") 103 .DefineFragment(80, 4, (uint)sdCapacityParameters.BlockSize, name: "max read data block length") 104 .DefineFragment(84, 12, (uint)( 105 CardCommandClass.Class0 106 | CardCommandClass.Class2 107 | CardCommandClass.Class4 108 ), name: "card command classes") 109 .DefineFragment(96, 3, (uint)TransferRate.Transfer10Mbit, name: "transfer rate unit") 110 .DefineFragment(99, 5, (uint)TransferMultiplier.Multiplier2_5, name: "transfer multiplier") 111 .DefineFragment(126, 2, (uint)CSD.Version2, name: "CSD structure") 112 ; 113 } 114 115 extendedCardSpecificDataGenerator = new VariableLengthValue(4096) 116 .DefineFragment(120, 8, 1, name: "command queue enabled") 117 .DefineFragment(200, 1, 1, name: "HS400 support") 118 .DefineFragment(1472, 8, 1, name: "es support") 119 .DefineFragment(1480, 8, 1, name: "hw hs timing") 120 .DefineFragment(1568, 8, (uint)DeviceType.SDR50Mhz | (uint) DeviceType.HS200, name: "device type") 121 .DefineFragment(2464, 8, 1, name: "command queue support") 122 ; 123 124 cardIdentificationGenerator = new VariableLengthValue(128) 125 .DefineFragment(8, 4, 8, name: "manufacturer date code - month") 126 .DefineFragment(12, 8, 18, name: "manufacturer date code - year") 127 .DefineFragment(64, 8, (uint)'D', name: "product name 5") 128 .DefineFragment(72, 8, (uint)'O', name: "product name 4") 129 .DefineFragment(80, 8, (uint)'N', name: "product name 3") 130 .DefineFragment(88, 8, (uint)'E', name: "product name 2") 131 .DefineFragment(96, 8, (uint)'R', name: "product name 1") 132 .DefineFragment(120, 8, 0xab, name: "manufacturer ID") 133 ; 134 135 switchFunctionStatusGenerator = new VariableLengthValue(512) 136 .DefineFragment(128, 1, 0x1, name: "Function Number/Status Code") 137 ; 138 139 cardConfigurationGenerator = new VariableLengthValue(64) 140 .DefineFragment(0, 32, 0, name: "reserved") 141 .DefineFragment(32, 16, 0, name: "reserved") 142 .DefineFragment(48, 4, 5, name: "DAT Bus width supported") // DAT0 (1-bit) and DAT0-3 (4-bit) 143 .DefineFragment(52, 3, 0, name: "SD Security Support") // 0: No security 144 .DefineFragment(55, 1, 0, name: "data_status_after erases") 145 .DefineFragment(56, 4, 0, name: "SD Card - Spec. Version") // 0: Version 1.0-1.01 146 .DefineFragment(60, 4, 0, name: "SCR Structure") // 0: SCR version No 1.0 147 ; 148 149 operatingVoltageGenerator = new VariableLengthValue(24) 150 .DefineFragment(0, 4, 0x1, name: "voltage accepted") // 0x1: 2.7-3.6V 151 .DefineFragment(4, 16, 0, name: "reserved") 152 .DefineFragment(20, 4, 0, name: "command version"); 153 ; 154 155 crcEngine = new CRCEngine(0x1021, 16, false, false, 0x00); 156 var bufferSize = highCapacityMode ? HighCapacityBlockLength : blockLengthInBytes; 157 /* 158 * enough to hold: 159 * 1 byte - start block token 160 * bufferSize bytes - actual data 161 * 2 bytes - CRC 162 * 1 byte - dummy byte required for the read transaction 163 */ 164 spiContext.DataBuffer = new byte[bufferSize + 4]; 165 } 166 Reset()167 public void Reset() 168 { 169 GoToIdle(); 170 171 var sdCapacityParameters = SDHelpers.SeekForCapacityParameters(capacity, blockSize); 172 blockLengthInBytes = SDHelpers.BlockLengthInBytes(sdCapacityParameters.BlockSize); 173 } 174 Dispose()175 public void Dispose() 176 { 177 dataBackend.Dispose(); 178 } 179 HandleCommand(uint commandIndex, uint arg)180 public BitStream HandleCommand(uint commandIndex, uint arg) 181 { 182 BitStream result; 183 this.Log(LogLevel.Noisy, "Command received: 0x{0:x} with arg 0x{1:x}", commandIndex, arg); 184 var treatNextCommandAsAppCommandLocal = treatNextCommandAsAppCommand; 185 treatNextCommandAsAppCommand = false; 186 if(!treatNextCommandAsAppCommandLocal || !TryHandleApplicationSpecificCommand((SdCardApplicationSpecificCommand)commandIndex, arg, out result)) 187 { 188 result = HandleStandardCommand((SdCardCommand)commandIndex, arg); 189 } 190 this.Log(LogLevel.Noisy, "Sending command response: {0}", result.ToString()); 191 return result; 192 } 193 WriteData(byte[] data)194 public void WriteData(byte[] data) 195 { 196 WriteData(data, data.Length); 197 } 198 ReadData(uint size)199 public byte[] ReadData(uint size) 200 { 201 byte[] result; 202 if(readContext.Data != null) 203 { 204 result = readContext.Data.AsByteArray(readContext.Offset, size); 205 Array.Reverse(result); 206 readContext.Move(size * 8); 207 } 208 else 209 { 210 result = ReadDataFromUnderlyingFile(readContext.Offset, checked((int)size)); 211 readContext.Move(size); 212 } 213 return result; 214 } 215 Transmit(byte data)216 public byte Transmit(byte data) 217 { 218 if(!spiMode) 219 { 220 this.Log(LogLevel.Error, "Received data over SPI, but the SPI mode is disabled."); 221 return 0; 222 } 223 224 this.Log(LogLevel.Noisy, "SPI: Received byte 0x{0:X} in state {1}", data, spiContext.State); 225 226 switch(spiContext.State) 227 { 228 case SpiState.WaitingForCommand: 229 { 230 if(spiContext.IoState == IoState.Idle && data == DummyByte) 231 { 232 this.Log(LogLevel.Noisy, "Received a DUMMY byte in the idle state, ignoring it"); 233 break; 234 } 235 236 if((spiContext.IoState == IoState.Idle || spiContext.IoState == IoState.MultipleBlockRead) && data != DummyByte) 237 { 238 // two MSB of the SPI command byte should be '01' 239 if(BitHelper.IsBitSet(data, 7) || !BitHelper.IsBitSet(data, 6)) 240 { 241 this.Log(LogLevel.Warning, "Unexpected command number value 0x{0:X}, ignoring this - expect problems", data); 242 return GenerateR1Response(illegalCommand: true).AsByte(); 243 } 244 245 // clear COMMAND bit, we don't need it anymore 246 BitHelper.ClearBits(ref data, 6); 247 248 spiContext.CommandNumber = (uint)data; 249 spiContext.ArgumentBytes = 0; 250 spiContext.State = SpiState.WaitingForArgBytes; 251 252 break; 253 } 254 255 switch(spiContext.IoState) 256 { 257 case IoState.SingleBlockRead: 258 case IoState.MultipleBlockRead: 259 return HandleRead(); 260 case IoState.SingleBlockWrite: 261 case IoState.MultipleBlockWrite: 262 var ret = HandleWrite(data); 263 return ret; 264 } 265 266 break; 267 } 268 269 case SpiState.WaitingForArgBytes: 270 { 271 this.Log(LogLevel.Noisy, "Storing as arg byte #{0}", spiContext.ArgumentBytes); 272 273 spiContext.Argument <<= 8; 274 spiContext.Argument |= data; 275 spiContext.ArgumentBytes++; 276 277 if(spiContext.ArgumentBytes == 4) 278 { 279 spiContext.State = SpiState.WaitingForCRC; 280 } 281 break; 282 } 283 284 case SpiState.WaitingForCRC: 285 { 286 // we don't check CRC 287 288 this.Log(LogLevel.Noisy, "Sending a command to the SD card"); 289 var result = HandleCommand(spiContext.CommandNumber, spiContext.Argument).AsByteArray(); 290 291 if(result.Length == 0) 292 { 293 this.Log(LogLevel.Warning, "Received an empty response, this is strange and might cause problems!"); 294 spiContext.State = SpiState.WaitingForCommand; 295 } 296 else 297 { 298 // The response is sent back within command response time, 299 // 0 to 8 bytes for SDC, 1 to 8 bytes for MMC. 300 // Send single dummy byte for compatibility with both cases. 301 spiContext.ResponseBuffer.Enqueue(DummyByte); 302 303 spiContext.ResponseBuffer.EnqueueRange(result); 304 spiContext.State = SpiState.SendingResponse; 305 } 306 break; 307 } 308 309 case SpiState.SendingResponse: 310 { 311 spiContext.ResponseBuffer.TryDequeue(out var res); 312 313 if(spiContext.ResponseBuffer.Count == 0) 314 { 315 this.Log(LogLevel.Noisy, "This is the end of response buffer"); 316 spiContext.State = SpiState.WaitingForCommand; 317 } 318 return res; 319 } 320 321 default: 322 { 323 throw new ArgumentException($"Received data 0x{data:X} in an unexpected state {spiContext.State}"); 324 } 325 } 326 327 return DummyByte; 328 } 329 FinishTransmission()330 public void FinishTransmission() 331 { 332 if(!spiMode) 333 { 334 this.Log(LogLevel.Error, "Received SPI transmission finish signal, but the SPI mode is disabled."); 335 return; 336 } 337 338 this.Log(LogLevel.Noisy, "Finishing transmission"); 339 spiContext.Reset(); 340 } 341 ReadSwitchFunctionStatusRegister()342 public byte[] ReadSwitchFunctionStatusRegister() 343 { 344 return switchFunctionStatusGenerator.Bits.AsByteArray(); 345 } 346 ReadExtendedCardSpecificDataRegister()347 public byte[] ReadExtendedCardSpecificDataRegister() 348 { 349 return extendedCardSpecificDataGenerator.Bits.AsByteArray(); 350 } 351 352 public ushort CardAddress { get; set; } 353 354 public BitStream CardStatus => cardStatusGenerator.Bits; 355 356 public BitStream OperatingConditions => operatingConditionsGenerator.Bits; 357 358 public BitStream SDConfiguration => cardConfigurationGenerator.Bits; 359 360 public BitStream SDStatus => new VariableLengthValue(512).Bits; 361 362 public BitStream CardSpecificData => cardSpecificDataGenerator.Bits; 363 364 public BitStream CardIdentification => cardIdentificationGenerator.Bits; 365 366 public BitStream OperatingVoltage => operatingVoltageGenerator.Bits; 367 WriteData(byte[] data, int length)368 private void WriteData(byte[] data, int length) 369 { 370 WriteDataToUnderlyingFile(writeContext.Offset, length, data); 371 writeContext.Move((uint)length); 372 state = SDCardState.Transfer; 373 } 374 WriteDataToUnderlyingFile(long offset, int size, byte[] data)375 private void WriteDataToUnderlyingFile(long offset, int size, byte[] data) 376 { 377 dataBackend.Position = offset; 378 var actualSize = checked((int)Math.Min(size, dataBackend.Length - dataBackend.Position)); 379 if(actualSize < size) 380 { 381 this.Log(LogLevel.Warning, "Tried to write {0} bytes of data to offset {1}, but space for only {2} is available.", size, offset, actualSize); 382 } 383 dataBackend.Write(data, 0, actualSize); 384 } 385 ReadDataFromUnderlyingFile(long offset, int size)386 private byte[] ReadDataFromUnderlyingFile(long offset, int size) 387 { 388 dataBackend.Position = offset; 389 var actualSize = checked((int)Math.Min(size, dataBackend.Length - dataBackend.Position)); 390 if(actualSize < size) 391 { 392 this.Log(LogLevel.Warning, "Tried to read {0} bytes of data from offset {1}, but only {2} is available.", size, offset, actualSize); 393 } 394 395 /* During multi-block read, when reading till the end of disk, the SD card could reach end of disk before receiving 396 * stop transmission command. SD card specification doesn't specify what should be done in such situation. 397 * Return 0s as missing bytes. 398 */ 399 var result = new byte[size]; 400 var readSoFar = 0; 401 while(readSoFar < actualSize) 402 { 403 var readThisTime = dataBackend.Read(result, readSoFar, actualSize - readSoFar); 404 if(readThisTime == 0) 405 { 406 // this should not happen as we calculated the available data size 407 throw new ArgumentException("Unexpected end of data in file stream"); 408 } 409 readSoFar += readThisTime; 410 } 411 412 return result; 413 } 414 GoToIdle()415 private void GoToIdle() 416 { 417 readContext.Reset(); 418 writeContext.Reset(); 419 treatNextCommandAsAppCommand = false; 420 421 state = SDCardState.Idle; 422 423 spiContext.Reset(); 424 } 425 426 /* Data packet has the following format: 427 * bytes: 428 * [ 0 ] data token 429 * [ 1 : blockSize ] actual data 430 * [ blocksSize+1 : blockSize+2 ] CRC 431 * 432 * After sending CRC, we have to send single DummyByte before sending next 433 * data packet. 434 */ HandleRead()435 private byte HandleRead() 436 { 437 var blockSize = highCapacityMode ? HighCapacityBlockLength : blockLengthInBytes; 438 ushort crc = 0; 439 440 if(spiContext.BytesSent == 0) 441 { 442 var readData = ReadData(blockSize); 443 crc = (ushort)crcEngine.Calculate(readData); 444 445 spiContext.DataBuffer[0] = BlockBeginIndicator; 446 System.Array.Copy(readData, 0, spiContext.DataBuffer, 1, blockSize); 447 spiContext.DataBuffer[blockSize + 1] = crc.HiByte(); 448 spiContext.DataBuffer[blockSize + 2] = crc.LoByte(); 449 // before sending new packet, at least one DummyByte should be sent 450 spiContext.DataBuffer[blockSize + 3] = DummyByte; 451 } 452 453 var res = spiContext.DataBuffer[spiContext.BytesSent]; 454 455 spiContext.BytesSent++; 456 // We sent whole required data and can proceed to the next data packet, 457 // or finish the data read. 458 if(spiContext.BytesSent == blockSize + 4) 459 { 460 if(spiContext.IoState == IoState.SingleBlockRead) 461 { 462 spiContext.IoState = IoState.Idle; 463 } 464 spiContext.BytesSent = 0; 465 } 466 return res; 467 } 468 469 /* Data packet has the following format: 470 * bytes: 471 * [ 0 ] data token 472 * [ 1 : blockSize ] actual data 473 * [ blocksSize+1 : blockSize+2 ] CRC 474 * 475 * After sending CRC, we have to send data response. 476 */ HandleWrite(byte data)477 private byte HandleWrite(byte data) 478 { 479 var blockSize = highCapacityMode ? HighCapacityBlockLength : blockLengthInBytes; 480 481 switch(spiContext.ReceptionState) 482 { 483 case ReceptionState.WaitingForDataToken: 484 switch((DataToken)data) 485 { 486 case DataToken.StopTran: 487 spiContext.IoState = IoState.Idle; 488 state = SDCardState.Programming; 489 break; 490 case DataToken.SingleWriteStartBlock: 491 case DataToken.MultiWriteStartBlock: 492 spiContext.DataBytesReceived = 0; 493 spiContext.ReceptionState = ReceptionState.ReceivingData; 494 break; 495 } 496 return DummyByte; 497 case ReceptionState.ReceivingData: 498 spiContext.DataBuffer[spiContext.DataBytesReceived] = data; 499 spiContext.DataBytesReceived++; 500 if(spiContext.DataBytesReceived == blockSize) 501 { 502 spiContext.ReceptionState = ReceptionState.ReceivingCRC; 503 spiContext.CRCBytesReceived = 0; 504 } 505 return DummyByte; 506 case ReceptionState.ReceivingCRC: 507 spiContext.CRCBytesReceived++; 508 if(spiContext.CRCBytesReceived == 2) 509 { 510 spiContext.ReceptionState = ReceptionState.SendingResponse; 511 } 512 return DummyByte; 513 case ReceptionState.SendingResponse: 514 WriteData(spiContext.DataBuffer, (int)blockSize); 515 spiContext.ReceptionState = ReceptionState.WaitingForDataToken; 516 if(spiContext.IoState == IoState.SingleBlockWrite) 517 { 518 spiContext.IoState = IoState.Idle; 519 state = SDCardState.Programming; 520 } 521 return DataAcceptedResponse; 522 } 523 return DummyByte; 524 } 525 GenerateR1Response(bool illegalCommand = false)526 private BitStream GenerateR1Response(bool illegalCommand = false) 527 { 528 return new BitStream() 529 .AppendBit(state == SDCardState.Idle) 530 .AppendBit(false) // Erase Reset 531 .AppendBit(illegalCommand) 532 .AppendBit(false) // Com CRC Error 533 .AppendBit(false) // Erase Seq Error 534 .AppendBit(false) // Address Error 535 .AppendBit(false) // Parameter Error 536 .AppendBit(false); // always 0 537 } 538 GenerateR2Response()539 private BitStream GenerateR2Response() 540 { 541 return GenerateR1Response() 542 .Append((byte)0); // TODO: fill with the actual data 543 } 544 GenerateR3Response()545 private BitStream GenerateR3Response() 546 { 547 return GenerateR1Response() 548 .Append(OperatingConditions.AsByteArray()); 549 } 550 GenerateR7Response(byte checkPattern)551 private BitStream GenerateR7Response(byte checkPattern) 552 { 553 return GenerateR1Response() 554 .Append(OperatingVoltage.AsByteArray().Reverse().ToArray()) 555 .Append(checkPattern); 556 } 557 GenerateRegisterResponse(BitStream register)558 private BitStream GenerateRegisterResponse(BitStream register) 559 { 560 var reg = register.AsByteArray().Reverse().ToArray(); 561 ushort crc = (ushort)crcEngine.Calculate(reg); 562 return GenerateR1Response() 563 .Append(BlockBeginIndicator) 564 .Append(reg) 565 .Append(crc.HiByte()) 566 .Append(crc.LoByte()); 567 } 568 HandleStandardCommand(SdCardCommand command, uint arg)569 private BitStream HandleStandardCommand(SdCardCommand command, uint arg) 570 { 571 this.Log(LogLevel.Noisy, "Handling as a standard command: {0}", command); 572 switch(command) 573 { 574 case SdCardCommand.GoIdleState_CMD0: 575 GoToIdle(); 576 return spiMode 577 ? GenerateR1Response() 578 : BitStream.Empty; // no response in SD mode 579 580 case SdCardCommand.SendSupportInformation_CMD1: 581 return spiMode 582 ? GenerateR3Response() 583 : OperatingConditions; 584 585 case SdCardCommand.SendCardIdentification_CMD2: 586 { 587 if(spiMode) 588 { 589 // this command is not supported in the SPI mode 590 break; 591 } 592 593 state = SDCardState.Identification; 594 595 return CardIdentification; 596 } 597 598 case SdCardCommand.SendRelativeAddress_CMD3: 599 { 600 if(spiMode) 601 { 602 // this command is not supported in the SPI mode 603 break; 604 } 605 606 state = SDCardState.Standby; 607 608 var status = CardStatus.AsUInt32(); 609 return BitHelper.BitConcatenator.New() 610 .StackAbove(status, 13, 0) 611 .StackAbove(status, 1, 19) 612 .StackAbove(status, 2, 22) 613 .StackAbove(CardAddress, 16, 0) 614 .Bits; 615 } 616 617 case SdCardCommand.CheckSwitchableFunction_CMD6: 618 return spiMode 619 ? GenerateR1Response() 620 : CardStatus; 621 622 case SdCardCommand.SelectDeselectCard_CMD7: 623 { 624 if(spiMode) 625 { 626 // this command is not supported in the SPI mode 627 break; 628 } 629 630 // this is a toggle command: 631 // Select is used to start a transfer; 632 // Deselct is used to abort the active transfer 633 switch(state) 634 { 635 case SDCardState.Standby: 636 state = SDCardState.Transfer; 637 break; 638 639 case SDCardState.Transfer: 640 case SDCardState.Programming: 641 state = SDCardState.Standby; 642 break; 643 } 644 645 return CardStatus; 646 } 647 648 case SdCardCommand.SendInterfaceConditionCommand_CMD8: 649 return spiMode 650 ? GenerateR7Response((byte)arg) 651 : CardStatus; 652 653 case SdCardCommand.SendCardSpecificData_CMD9: 654 return spiMode 655 ? GenerateRegisterResponse(CardSpecificData) 656 : CardSpecificData; 657 658 case SdCardCommand.SendCardIdentification_CMD10: 659 return spiMode 660 ? GenerateRegisterResponse(CardIdentification) 661 : CardIdentification; 662 663 case SdCardCommand.StopTransmission_CMD12: 664 readContext.Reset(); 665 writeContext.Reset(); 666 667 switch(state) 668 { 669 case SDCardState.SendingData: 670 state = SDCardState.Transfer; 671 spiContext.IoState = IoState.Idle; 672 break; 673 674 case SDCardState.ReceivingData: 675 state = SDCardState.Programming; 676 break; 677 } 678 679 return spiMode 680 ? GenerateR1Response() 681 : CardStatus; 682 683 case SdCardCommand.SendStatus_CMD13: 684 return spiMode 685 ? GenerateR2Response() 686 : CardStatus; 687 688 case SdCardCommand.SetBlockLength_CMD16: 689 blockLengthInBytes = arg; 690 return spiMode 691 ? GenerateR1Response() 692 : CardStatus; 693 694 case SdCardCommand.ReadSingleBlock_CMD17: 695 spiContext.IoState = IoState.SingleBlockRead; 696 state = SDCardState.SendingData; 697 spiContext.BytesSent = 0; 698 readContext.Offset = highCapacityMode 699 ? arg * HighCapacityBlockLength 700 : arg; 701 return spiMode 702 ? GenerateR1Response() 703 : CardStatus; 704 705 case SdCardCommand.ReadMultipleBlocks_CMD18: 706 spiContext.IoState = IoState.MultipleBlockRead; 707 state = SDCardState.SendingData; 708 spiContext.BytesSent = 0; 709 readContext.Offset = highCapacityMode 710 ? arg * HighCapacityBlockLength 711 : arg; 712 return spiMode 713 ? GenerateR1Response() 714 : CardStatus; 715 716 case SdCardCommand.SendTuneBlock_CMD21: 717 return new BitStream(new byte[4]); 718 719 case SdCardCommand.SetBlockCount_CMD23: 720 return spiMode 721 ? GenerateR1Response() 722 : CardStatus; 723 724 case SdCardCommand.WriteSingleBlock_CMD24: 725 state = SDCardState.ReceivingData; 726 spiContext.IoState = IoState.SingleBlockWrite; 727 spiContext.DataBytesReceived = 0; 728 spiContext.ReceptionState = ReceptionState.WaitingForDataToken; 729 writeContext.Offset = highCapacityMode 730 ? arg * HighCapacityBlockLength 731 : arg; 732 return spiMode 733 ? GenerateR1Response() 734 : CardStatus; 735 736 case SdCardCommand.WriteMultipleBlocks_CMD25: 737 state = SDCardState.ReceivingData; 738 spiContext.IoState = IoState.MultipleBlockWrite; 739 spiContext.DataBytesReceived = 0; 740 spiContext.ReceptionState = ReceptionState.WaitingForDataToken; 741 writeContext.Offset = highCapacityMode 742 ? arg * HighCapacityBlockLength 743 : arg; 744 return spiMode 745 ? GenerateR1Response() 746 : CardStatus; 747 748 case SdCardCommand.AppCommand_CMD55: 749 treatNextCommandAsAppCommand = true; 750 return spiMode 751 ? GenerateR1Response() 752 : CardStatus; 753 754 case SdCardCommand.ReadOperationConditionRegister_CMD58: 755 return spiMode 756 ? GenerateR3Response() 757 : BitStream.Empty; 758 759 case SdCardCommand.EnableCRCChecking_CMD59: 760 // we don't have to check CRC, but the software requires proper response after such request 761 return spiMode 762 ? GenerateR1Response() 763 : BitStream.Empty; 764 } 765 766 this.Log(LogLevel.Warning, "Unsupported command: {0}. Ignoring it", command); 767 return spiMode 768 ? GenerateR1Response(illegalCommand: true) 769 : BitStream.Empty; 770 } 771 TryHandleApplicationSpecificCommand(SdCardApplicationSpecificCommand command, uint arg, out BitStream result)772 private bool TryHandleApplicationSpecificCommand(SdCardApplicationSpecificCommand command, uint arg, out BitStream result) 773 { 774 this.Log(LogLevel.Noisy, "Handling as an application specific command: {0}", command); 775 switch(command) 776 { 777 case SdCardApplicationSpecificCommand.SendSDCardStatus_ACMD13: 778 readContext.Data = SDStatus; 779 result = spiMode 780 ? GenerateR2Response() 781 : CardStatus; 782 return true; 783 784 case SdCardApplicationSpecificCommand.SendOperatingConditionRegister_ACMD41: 785 // If HCS is set to 0, High Capacity SD Memory Card never returns ready state 786 var hcs = BitHelper.IsBitSet(arg, 30); 787 if(!highCapacityMode || hcs) 788 { 789 // activate the card 790 state = SDCardState.Ready; 791 } 792 793 result = spiMode 794 ? GenerateR1Response() 795 : OperatingConditions; 796 return true; 797 798 case SdCardApplicationSpecificCommand.SendSDConfigurationRegister_ACMD51: 799 readContext.Data = SDConfiguration; 800 state = SDCardState.SendingData; 801 result = spiMode 802 ? GenerateRegisterResponse(SDConfiguration) 803 : CardStatus; 804 return true; 805 806 default: 807 this.Log(LogLevel.Noisy, "Command #{0} seems not to be any application specific command", command); 808 result = null; 809 return false; 810 } 811 } 812 813 private SDCardState state; 814 815 private bool treatNextCommandAsAppCommand; 816 private uint blockLengthInBytes; 817 private IoContext writeContext; 818 private IoContext readContext; 819 private readonly Stream dataBackend; 820 private readonly VariableLengthValue cardStatusGenerator; 821 private readonly VariableLengthValue cardConfigurationGenerator; 822 private readonly VariableLengthValue operatingConditionsGenerator; 823 private readonly VariableLengthValue cardSpecificDataGenerator; 824 private readonly VariableLengthValue extendedCardSpecificDataGenerator; 825 private readonly VariableLengthValue cardIdentificationGenerator; 826 private readonly VariableLengthValue switchFunctionStatusGenerator; 827 private readonly VariableLengthValue operatingVoltageGenerator; 828 829 private readonly long capacity; 830 private readonly BlockLength blockSize; 831 private readonly bool spiMode; 832 private readonly bool highCapacityMode; 833 private readonly SpiContext spiContext; 834 private readonly CRCEngine crcEngine; 835 private const byte DummyByte = 0xFF; 836 private const byte BlockBeginIndicator = 0xFE; 837 private const int HighCapacityBlockLength = 512; 838 private const byte DataAcceptedResponse = 0x05; 839 840 private struct IoContext 841 { 842 public uint Offset 843 { 844 get { return offset; } 845 set 846 { 847 offset = value; 848 data = null; 849 } 850 } 851 852 public BitStream Data 853 { 854 get { return data; } 855 set 856 { 857 data = value; 858 offset = 0; 859 } 860 } 861 MoveAntmicro.Renode.Peripherals.SD.SDCard.IoContext862 public void Move(uint offset) 863 { 864 this.offset += offset; 865 if(data == null) 866 { 867 bytesLeft -= offset; 868 } 869 } 870 ResetAntmicro.Renode.Peripherals.SD.SDCard.IoContext871 public void Reset() 872 { 873 offset = 0; 874 bytesLeft = 0; 875 data = null; 876 } 877 878 private uint bytesLeft; 879 private uint offset; 880 private BitStream data; 881 } 882 883 private enum SdCardCommand 884 { 885 GoIdleState_CMD0 = 0, 886 SendSupportInformation_CMD1 = 1, 887 SendCardIdentification_CMD2 = 2, 888 SendRelativeAddress_CMD3 = 3, 889 CheckSwitchableFunction_CMD6 = 6, 890 SelectDeselectCard_CMD7 = 7, 891 // this command has been added in spec version 2.0 - we don't have to answer to it 892 SendInterfaceConditionCommand_CMD8 = 8, 893 SendCardSpecificData_CMD9 = 9, 894 SendCardIdentification_CMD10 = 10, 895 StopTransmission_CMD12 = 12, 896 SendStatus_CMD13 = 13, 897 SetBlockLength_CMD16 = 16, 898 ReadSingleBlock_CMD17 = 17, 899 ReadMultipleBlocks_CMD18 = 18, 900 SendTuneBlock_CMD21 = 21, 901 SetBlockCount_CMD23 = 23, 902 WriteSingleBlock_CMD24 = 24, 903 WriteMultipleBlocks_CMD25 = 25, 904 IOReadWriteDirect_CM52 = 52, 905 AppCommand_CMD55 = 55, 906 ReadOperationConditionRegister_CMD58 = 58, 907 EnableCRCChecking_CMD59 = 59 908 } 909 910 private enum SdCardApplicationSpecificCommand 911 { 912 SendSDCardStatus_ACMD13 = 13, 913 SendOperatingConditionRegister_ACMD41 = 41, 914 SendSDConfigurationRegister_ACMD51 = 51 915 } 916 917 [Flags] 918 private enum CardCommandClass 919 { 920 Class0 = (1 << 0), 921 Class1 = (1 << 1), 922 Class2 = (1 << 2), 923 Class3 = (1 << 3), 924 Class4 = (1 << 4), 925 Class5 = (1 << 5), 926 Class6 = (1 << 6), 927 Class7 = (1 << 7), 928 Class8 = (1 << 8), 929 Class9 = (1 << 9), 930 Class10 = (1 << 10), 931 Class11 = (1 << 11) 932 } 933 934 private enum TransferRate 935 { 936 Transfer100kbit = 0, 937 Transfer1Mbit = 1, 938 Transfer10Mbit = 2, 939 Transfer100Mbit = 3, 940 // the rest is reserved 941 } 942 943 private enum TransferMultiplier 944 { 945 Reserved = 0, 946 Multiplier1 = 1, 947 Multiplier1_2 = 2, 948 Multiplier1_3 = 3, 949 Multiplier1_5 = 4, 950 Multiplier2 = 5, 951 Multiplier2_5 = 6, 952 Multiplier3 = 7, 953 Multiplier3_5 = 8, 954 Multiplier4 = 9, 955 Multiplier4_5 = 10, 956 Multiplier5 = 11, 957 Multiplier5_5 = 12, 958 Multiplier6 = 13, 959 Multiplier7 = 14, 960 Multiplier8 = 15 961 } 962 963 private enum DeviceType 964 { 965 Legacy = 0, 966 SDR25Mhz = 1, 967 SDR50Mhz = 2, 968 SDR = 3, 969 DDR = 4, 970 HS200 = 0x10 971 } 972 973 private enum DataToken 974 { 975 SingleWriteStartBlock = 0xFE, 976 MultiWriteStartBlock = 0xFC, 977 StopTran = 0xFD 978 } 979 980 private enum SpiState 981 { 982 WaitingForCommand, 983 WaitingForArgBytes, 984 WaitingForCRC, 985 SendingResponse 986 } 987 988 private enum IoState 989 { 990 Idle, 991 SingleBlockRead, 992 MultipleBlockRead, 993 SingleBlockWrite, 994 MultipleBlockWrite 995 } 996 997 private enum ReceptionState 998 { 999 WaitingForDataToken, 1000 ReceivingData, 1001 ReceivingCRC, 1002 SendingResponse 1003 } 1004 1005 private class SpiContext 1006 { Reset()1007 public void Reset() 1008 { 1009 ResponseBuffer.Clear(); 1010 ArgumentBytes = 0; 1011 Argument = 0; 1012 CommandNumber = 0; 1013 State = SpiState.WaitingForCommand; 1014 BytesSent = 0; 1015 IoState = IoState.Idle; 1016 } 1017 1018 public Queue<byte> ResponseBuffer = new Queue<byte>(); 1019 public byte[] DataBuffer; 1020 public int ArgumentBytes; 1021 public uint Argument; 1022 public uint CommandNumber; 1023 public SpiState State; 1024 public uint BytesSent; 1025 public uint DataBytesReceived; 1026 public uint CRCBytesReceived; 1027 public IoState IoState; 1028 public ReceptionState ReceptionState; 1029 } 1030 1031 private enum SDCardState 1032 { 1033 Idle = 0, 1034 Ready = 1, 1035 Identification = 2, 1036 Standby = 3, 1037 Transfer = 4, 1038 SendingData = 5, 1039 ReceivingData = 6, 1040 Programming = 7, 1041 Disconnect = 8 1042 // the rest is reserved 1043 } 1044 1045 private enum CSD 1046 { 1047 Version1 = 0, 1048 Version2 = 1 1049 } 1050 } 1051 } 1052