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 System; 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Logging; 11 using Antmicro.Renode.Peripherals.Bus; 12 using System.Collections.Generic; 13 using Antmicro.Migrant; 14 15 namespace Antmicro.Renode.Peripherals.UART 16 { 17 [AllowedTranslations(AllowedTranslation.WordToDoubleWord)] 18 public class NS16550 : IBytePeripheral, IDoubleWordPeripheral, IUART, IKnownSize 19 { NS16550(bool wideRegisters = false)20 public NS16550(bool wideRegisters = false) 21 { 22 mode32 = wideRegisters; 23 IRQ = new GPIO(); 24 Reset(); 25 } 26 27 public GPIO IRQ { get; private set; } 28 29 public long Size 30 { 31 get 32 { 33 return 0x100; 34 } 35 } 36 WriteChar(byte value)37 public void WriteChar(byte value) 38 { 39 lock(UARTLock) 40 { 41 if((fifoControl & FifoControl.Enable) != 0 || true)//HACK : fifo always enabled 42 { 43 recvFifo.Enqueue(value); 44 lineStatus |= LineStatus.DataReady; 45 } 46 else 47 { 48 if((lineStatus & LineStatus.DataReady) != 0) 49 { 50 lineStatus |= LineStatus.OverrunErrorIndicator; 51 } 52 receiverBuffer = value; 53 lineStatus |= LineStatus.DataReady; 54 } 55 Update(); 56 } 57 } 58 WriteByte(long offset, byte value)59 public void WriteByte(long offset, byte value) 60 { 61 var originalOffset = offset; 62 if(mode32 && ((offset % 4) == 0)) 63 { 64 offset = offset / 4; 65 } 66 lock(UARTLock) 67 { 68 if((lineControl & LineControl.DivisorLatchAccess) != 0) 69 { 70 switch((Register)offset) 71 { 72 case Register.DivisorLatchL: 73 divider = (ushort)((divider & 0xff00) | value); 74 return; 75 76 case Register.DivisorLatchH: 77 divider = (ushort)((divider & 0x00ff) | (value << 8)); 78 return; 79 80 case Register.PrescalerDivision: 81 prescaler = (byte)(value & 0x0f); 82 return; 83 } 84 } 85 86 switch((Register)offset) 87 { 88 case Register.Data: 89 var handler = CharReceived; 90 if(handler != null) 91 { 92 handler((byte)(value & 0xFF)); 93 } 94 95 transmitNotPending = 0; 96 lineStatus &= ~LineStatus.TransmitHoldEmpty; 97 if((fifoControl & FifoControl.IsEnabled) != 0) 98 { 99 lineStatus &= ~LineStatus.TransmitterEmpty; 100 } 101 Update(); 102 103 if((fifoControl & FifoControl.IsEnabled) == 0 || (interruptEnable & InterruptEnableLevel.ProgrammableTransmitHoldEmptyInterruptMode) == 0) 104 { 105 lineStatus |= LineStatus.TransmitHoldEmpty; 106 } 107 lineStatus |= LineStatus.TransmitterEmpty; 108 transmitNotPending = 1; 109 Update(); 110 break; 111 112 case Register.InterruptEnable: 113 interruptEnable = (InterruptEnableLevel)value; 114 if((fifoControl & FifoControl.IsEnabled) != 0 && (interruptEnable & InterruptEnableLevel.ProgrammableTransmitHoldEmptyInterruptMode) != 0) 115 { 116 lineStatus &= ~LineStatus.TransmitHoldEmpty; 117 } 118 119 if((lineStatus & LineStatus.TransmitHoldEmpty) != 0) 120 { 121 transmitNotPending = 1; 122 Update(); 123 } 124 break; 125 126 case Register.FIFOControl: 127 var val = (FifoControl)value; 128 if(fifoControl == val) 129 { 130 break; 131 } 132 /* Did the enable/disable flag change? If so, make sure FIFOs get flushed */ 133 if(((val ^ fifoControl) & FifoControl.Enable) != 0) 134 { 135 val |= (FifoControl.TransmitReset | FifoControl.ReceiveReset); 136 } 137 138 /* FIFO clear */ 139 if((val & FifoControl.ReceiveReset) != 0) 140 { 141 recvFifo.Clear(); 142 143 } 144 if((val & FifoControl.TransmitReset) != 0) 145 { 146 //clear xmit 147 } 148 149 if((val & FifoControl.Enable) != 0) 150 { 151 interruptIdentification |= (InterruptLevel)FifoControl.IsEnabled; 152 /* Set RECV_FIFO trigger Level */ 153 switch(val & (FifoControl)0XC0) 154 { 155 case FifoControl.IrqTriggerLevel1: 156 interruptTriggerLevel = 1; 157 break; 158 case FifoControl.IrqTriggerLevel2: 159 interruptTriggerLevel = 4; 160 break; 161 case FifoControl.IrqTriggerLevel3: 162 interruptTriggerLevel = 8; 163 break; 164 case FifoControl.IrqTriggerLevel4: 165 interruptTriggerLevel = 14; 166 break; 167 } 168 } 169 else 170 { 171 interruptIdentification &= (InterruptLevel)unchecked((byte)(~FifoControl.IsEnabled)); 172 } 173 /* Set fifoControl - or at least the bits in it that are supposed to "stick" */ 174 fifoControl = (val & (FifoControl)0xC9); 175 Update(); 176 break; 177 178 case Register.LineControl: 179 lineControl = (LineControl)value; 180 break; 181 182 case Register.ModemControl: 183 modemControl = (ModemControl)(value & 0x1F); 184 break; 185 186 case Register.LineStatus: 187 //Linux should not write here, but it does 188 break; 189 190 case Register.TriggerLevelScratchpad: 191 scratchRegister = value; 192 break; 193 194 case Register.MultiModeControl0: 195 this.Log(LogLevel.Warning, "Unsupported write to LIN mode configuration register at offset 0x{0:X}.", originalOffset); 196 break; 197 case Register.MultiModeControl1: 198 this.Log(LogLevel.Warning, "Unsupported write to RZI mode configuration register at offset 0x{0:X}.", originalOffset); 199 break; 200 case Register.MultiModeControl2: 201 case Register.MultiModeInterruptEnable: 202 case Register.TransmitterTimeGuard: 203 case Register.ReceiverTimeOut: 204 this.Log(LogLevel.Warning, "Unsupported write to multi-mode configuration register at offset 0x{0:X}.", originalOffset); 205 break; 206 case Register.FractionalDivisor: 207 case Register.GlitchFilter: 208 this.Log(LogLevel.Warning, "Unsupported write to configuration register at offset 0x{0:X}.", originalOffset); 209 break; 210 211 default: 212 this.LogUnhandledWrite(originalOffset, value); 213 break; 214 } 215 216 } 217 } 218 ReadByte(long offset)219 public byte ReadByte(long offset) 220 { 221 var originalOffset = offset; 222 if(mode32 && ((offset % 4) == 0)) 223 { 224 offset = offset / 4; 225 } 226 lock(UARTLock) 227 { 228 byte value = 0x0; 229 if((lineControl & LineControl.DivisorLatchAccess) != 0) 230 { 231 switch((Register)offset) 232 { 233 case Register.DivisorLatchL: 234 value = (byte)(divider & 0xFF); 235 goto ret; 236 237 case Register.DivisorLatchH: 238 value = (byte)((divider >> 8) & 0xFF); 239 goto ret; 240 } 241 } 242 else 243 { 244 switch((Register)offset) 245 { 246 case Register.Data: 247 if((fifoControl & FifoControl.Enable) != 0 || true /*HACK*/) 248 { 249 if(recvFifo.Count > 0) 250 { 251 value = recvFifo.Dequeue(); 252 } 253 else 254 { 255 value = 0; 256 } 257 if(recvFifo.Count == 0) 258 { 259 lineStatus &= ~(LineStatus.DataReady | LineStatus.BreakIrqIndicator); 260 } 261 } 262 else 263 { 264 value = receiverBuffer; 265 lineStatus &= ~(LineStatus.DataReady | LineStatus.BreakIrqIndicator); 266 } 267 Update(); 268 if((modemControl & ModemControl.Loopback) == 0) 269 { 270 /* in loopback mode, don't receive any data */ 271 } 272 273 break; 274 275 case Register.InterruptEnable: 276 value = (byte)interruptEnable; 277 break; 278 279 case Register.InterruptIdentification: 280 value = (byte)interruptIdentification; 281 if((value & MaskInterruptId) == (byte)InterruptLevel.TransmitterHoldingRegEmpty) 282 { 283 transmitNotPending = 0; 284 Update(); 285 } 286 break; 287 288 case Register.LineControl: 289 value = (byte)lineControl; 290 break; 291 292 case Register.ModemControl: 293 //this.DebugLog("modem control read"); 294 value = (byte)modemControl; 295 break; 296 297 case Register.LineStatusHack: //TODO: HACK! Why does it work? 298 goto case Register.LineStatus; 299 300 case Register.LineStatus: 301 value = (byte)lineStatus; 302 if((lineStatus & (LineStatus.BreakIrqIndicator | LineStatus.OverrunErrorIndicator)) != 0) 303 { 304 lineStatus &= ~(LineStatus.BreakIrqIndicator | LineStatus.OverrunErrorIndicator); 305 Update(); 306 } 307 lineStatus &= ~(LineStatus.OverrunErrorIndicator | LineStatus.ParityErrorIndicator | LineStatus.FrameErrorIndicator | LineStatus.BreakIrqIndicator | LineStatus.ReceiverFIFOError); 308 break; 309 310 case Register.ModemStatusRegister: 311 // this.DebugLog("6 modem control read"); 312 if((modemControl & ModemControl.Loopback) != 0) 313 { 314 /* in loopback, the modem output pins are connected to the inputs */ 315 value = (byte)(((byte)modemControl & 0x0c) << 4); 316 value |= (byte)(((byte)modemControl & 0x02) << 3); 317 value |= (byte)(((byte)modemControl & 0x01) << 5); 318 } 319 else 320 { 321 value = (byte)modemStatus; 322 /* Clear delta bits & msr int after read, if they were set */ 323 if((modemStatus & ModemStatus.AnyDelta) != 0) 324 { 325 modemStatus &= (ModemStatus)0xF0; 326 Update(); 327 } 328 } 329 break; 330 331 case Register.TriggerLevelScratchpad: 332 value = scratchRegister; 333 break; 334 335 case Register.MultiModeControl0: 336 this.Log(LogLevel.Warning, "Unsupported read from LIN configuration register at offset 0x{0:X}.", originalOffset); 337 break; 338 case Register.MultiModeControl1: 339 this.Log(LogLevel.Warning, "Unsupported read from RZI configuration register at offset 0x{0:X}.", originalOffset); 340 break; 341 case Register.MultiModeControl2: 342 case Register.MultiModeInterruptEnable: 343 case Register.TransmitterTimeGuard: 344 case Register.ReceiverTimeOut: 345 this.Log(LogLevel.Warning, "Unsupported read from multi-mode configuration register at offset 0x{0:X}.", originalOffset); 346 break; 347 case Register.FractionalDivisor: 348 case Register.GlitchFilter: 349 this.Log(LogLevel.Warning, "Unsupported read from configuration register at offset 0x{0:X}.", originalOffset); 350 break; 351 352 default: 353 this.LogUnhandledRead(originalOffset); 354 break; 355 } 356 } 357 ret: 358 return value; 359 } 360 } 361 Reset()362 public void Reset() 363 { 364 lock(UARTLock) 365 { 366 receiverBuffer = 0; 367 interruptEnable = 0; 368 interruptIdentification = InterruptLevel.NoInterruptsPending; 369 lineControl = 0; 370 lineStatus = LineStatus.TransmitterEmpty | LineStatus.TransmitHoldEmpty; 371 modemStatus = ModemStatus.DataCarrierDetect | ModemStatus.DataSetReady | ModemStatus.ClearToSend; 372 divider = 0x0C; 373 modemControl = ModemControl.ForceDataCarrierDetect; 374 scratchRegister = 0; 375 transmitNotPending = 0; 376 } 377 } 378 ReadDoubleWord(long offset)379 public uint ReadDoubleWord(long offset) 380 { 381 return (uint)ReadByte(offset); 382 } 383 WriteDoubleWord(long offset, uint value)384 public void WriteDoubleWord(long offset, uint value) 385 { 386 WriteByte(offset, (byte)(value & 0xFF)); 387 } 388 Update()389 private void Update() 390 { 391 var interruptId = InterruptLevel.NoInterruptsPending; 392 if(((interruptEnable & InterruptEnableLevel.ReceiverLineStatus) != 0) && ((lineStatus & LineStatus.InterruptAny) != 0)) 393 { 394 interruptId = InterruptLevel.ReceiverLineStatusIrq; 395 } 396 else if(((interruptEnable & InterruptEnableLevel.ReceiverData) != 0) && ((lineStatus & LineStatus.DataReady) != 0) && (((fifoControl & FifoControl.Enable) == 0) || true /* HACK */ || recvFifo.Count > interruptTriggerLevel)) 397 { 398 interruptId = InterruptLevel.ReceiverDataIrq; 399 } 400 else if(((interruptEnable & InterruptEnableLevel.TransmitterHoldingReg) != 0) && (transmitNotPending != 0)) 401 { 402 interruptId = InterruptLevel.TransmitterHoldingRegEmpty; 403 } 404 else if(((interruptEnable & InterruptEnableLevel.ModemStatus) != 0) && ((modemStatus & ModemStatus.AnyDelta) != 0)) 405 { 406 interruptId = InterruptLevel.ModemStatusIrq; 407 } 408 409 interruptIdentification = interruptId | (interruptIdentification & (InterruptLevel)0xF0); 410 411 if(interruptId != InterruptLevel.NoInterruptsPending) 412 { 413 this.NoisyLog("IRQ true"); 414 IRQ.Set(true); 415 } 416 else 417 { 418 this.NoisyLog("IRQ false"); 419 IRQ.Set(false); 420 } 421 } 422 423 [field: Transient] 424 public event Action<byte> CharReceived; 425 426 private Queue<byte> recvFifo = new Queue<byte>(); 427 private object UARTLock = new object(); 428 429 private InterruptEnableLevel interruptEnable; 430 private InterruptLevel interruptIdentification; 431 /* read only */ 432 private LineControl lineControl; 433 private ModemControl modemControl; 434 private LineStatus lineStatus; 435 /* read only */ 436 private ModemStatus modemStatus; 437 /* read only */ 438 private FifoControl fifoControl; 439 private bool mode32; 440 private byte scratchRegister; 441 442 private byte interruptTriggerLevel; 443 private ushort divider; 444 private byte prescaler; 445 private byte receiverBuffer; 446 /* receive register */ 447 private int transmitNotPending; 448 449 private const int ReceiveFIFOSize = 16; 450 private const byte MaskInterruptId = 0x06; 451 /* Mask for the interrupt ID */ 452 453 454 private enum Register:uint 455 { 456 Data = 0x00, 457 DivisorLatchL = 0x00, 458 // the same as Data but accessible only when DLAB bit is set 459 InterruptEnable = 0x01, 460 DivisorLatchH = 0x01, 461 // the same as Interrupt enabel but accessible only when DLAB bit is set 462 InterruptIdentification = 0x02, 463 FIFOControl = 0x02, 464 LineControl = 0x03, 465 ModemControl = 0x04, 466 LineStatus = 0x05, 467 PrescalerDivision = 0x05, 468 // the same as Line Status but accessible only when DLAB bit is set 469 LineStatusHack = 0x14, 470 ModemStatusRegister = 0x06, 471 TriggerLevelScratchpad = 0x07, 472 473 MultiModeInterruptEnable = 0x09, 474 MultiModeControl0 = 0x0C, 475 MultiModeControl1 = 0x0D, 476 MultiModeControl2 = 0x0E, 477 FractionalDivisor = 0x0F, 478 GlitchFilter = 0x11, 479 TransmitterTimeGuard = 0x12, 480 ReceiverTimeOut = 0x13 481 } 482 483 [Flags] 484 private enum LineControl : byte 485 { 486 DivisorLatchAccess = 0x80, 487 ParityEnable = 0x08, 488 EvenParity = 0x10, 489 ForceParity = 0x20, 490 StopBits = 0x04, 491 WordLengthH = 0x02, 492 WordLengthL = 0x01 493 } 494 495 /* 496 * Interrupt trigger levels. The byte-counts are for 16550A - in newer UARTs the byte-count for each ITL is higher. 497 */ 498 [Flags] 499 private enum InterruptLevel : byte 500 { 501 NoInterruptsPending = 0x01, 502 TransmitterHoldingRegEmpty = 0x02, 503 ReceiverDataIrq = 0x04, 504 ReceiverLineStatusIrq = 0x06, 505 CharacterTimeoutIndication = 0x0C, 506 /*not used at the moment*/ 507 ModemStatusIrq = 0x00 508 /* "Other" irq - NoInterrupts is disabled, but no other bit is enabled, so check in another register */ 509 } 510 511 [Flags] 512 private enum InterruptEnableLevel : byte 513 { 514 ProgrammableTransmitHoldEmptyInterruptMode = 0x80, 515 ModemStatus = 0x08, 516 ReceiverLineStatus = 0x04, 517 TransmitterHoldingReg = 0x02, 518 ReceiverData = 0x01 519 } 520 521 /* 522 * These are the definitions for the Modem Control Register 523 * KKRU: This comment is useful as hell. 524 */ 525 [Flags] 526 private enum ModemControl : byte 527 { 528 Loopback = 0x10, 529 ForceDataCarrierDetect = 0x08, 530 ForceRingIndicator = 0x04, 531 ForceRequestToSend = 0x02, 532 ForceDataTerminalReady = 0x01 533 534 } 535 536 /* 537 * These are the definitions for the Modem Status Register 538 */ 539 [Flags] 540 private enum ModemStatus : byte 541 { 542 DataCarrierDetect = 0x80, 543 RingIndicator = 0x40, 544 DataSetReady = 0x20, 545 ClearToSend = 0x10, 546 DeltaDataCarrierDetect = 0x08, 547 TrailingEdgeRingIndicator = 0x04, 548 DeltaDataSetReady = 0x02, 549 DeltaClearToSend = 0x01, 550 AnyDelta = 0x0F 551 } 552 553 554 /* 555 * These are the definitions for the Line Status Register 556 */ 557 [Flags] 558 private enum LineStatus : byte 559 { 560 ReceiverFIFOError = 0x80, 561 TransmitterEmpty = 0x40, 562 TransmitHoldEmpty = 0x20, 563 BreakIrqIndicator = 0x10, 564 FrameErrorIndicator = 0x08, 565 ParityErrorIndicator = 0x04, 566 OverrunErrorIndicator = 0x02, 567 DataReady = 0x01, 568 InterruptAny = 0x1E 569 } 570 571 /* 572 * These are the definitions for the FIFO Control Register 573 */ 574 [Flags] 575 private enum FifoControl : byte 576 { 577 Enable = 0x01, 578 ReceiveReset = 0x02, 579 TransmitReset = 0x04, 580 DMAModeSelect = 0x08, 581 582 IsEnabledNotFunc = 0x80, 583 IsEnabled = 0xC0, 584 585 IrqTriggerLevel1 = 0x00, 586 IrqTriggerLevel2 = 0x40, 587 IrqTriggerLevel3 = 0x80, 588 IrqTriggerLevel4 = 0xC0 589 } 590 591 public Bits StopBits 592 { 593 get 594 { 595 if((lineControl & LineControl.StopBits) == 0) 596 { 597 return Bits.One; 598 } 599 // is word length is equal to 5? then 1.5 else 2 600 return ((byte)lineControl & 3u) == 0 ? Bits.OneAndAHalf : Bits.Two; 601 } 602 } 603 604 public Parity ParityBit 605 { 606 get 607 { 608 if((lineControl & LineControl.ParityEnable) == 0) 609 { 610 return Parity.None; 611 } 612 if((lineControl & LineControl.ForceParity) == 0) 613 { 614 return (lineControl & LineControl.EvenParity) == 0 ? Parity.Odd : Parity.Even; 615 } 616 return (lineControl & LineControl.EvenParity) == 0 ? Parity.Forced1 : Parity.Forced0; 617 } 618 } 619 620 public uint BaudRate 621 { 622 get 623 { 624 var divisor = (16 * (prescaler + 1) * divider); 625 return divisor == 0 ? 0 : (uint)(SystemClockFrequency / divisor); 626 } 627 } 628 629 private const uint SystemClockFrequency = 0; 630 } 631 } 632 633