HyperDbg Debugger
Loading...
Searching...
No Matches
apm88xxxx.c File Reference
#include "common.h"

Macros

#define CLOCK_RATE   3125000UL
 

Functions

BOOLEAN Uart16550InitializePortCommon (_In_opt_ _Null_terminated_ PCHAR LoadOptions, _Inout_ PCPPORT Port, BOOLEAN MemoryMapped, UCHAR AccessSize, UCHAR BitWidth)
 
BOOLEAN Uart16550SetBaudCommon (_Inout_ PCPPORT Port, ULONG Rate, ULONG Clock)
 
UART_STATUS Uart16550GetByte (_Inout_ PCPPORT Port, _Out_ PUCHAR Byte)
 
UART_STATUS Uart16550PutByte (_Inout_ PCPPORT Port, UCHAR Byte, BOOLEAN BusyWait)
 
BOOLEAN Uart16550RxReady (_Inout_ PCPPORT Port)
 
BOOLEAN Apm88xxxxInitializePort (_In_opt_ _Null_terminated_ PCHAR LoadOptions, _Inout_ PCPPORT Port, BOOLEAN MemoryMapped, UCHAR AccessSize, UCHAR BitWidth)
 
BOOLEAN Apm88xxxxSetBaud (_Inout_ PCPPORT Port, ULONG Rate)
 

Variables

UART_HARDWARE_DRIVER Apm88xxxxHardwareDriver
 

Macro Definition Documentation

◆ CLOCK_RATE

#define CLOCK_RATE   3125000UL

Function Documentation

◆ Apm88xxxxInitializePort()

BOOLEAN Apm88xxxxInitializePort ( _In_opt_ _Null_terminated_ PCHAR LoadOptions,
_Inout_ PCPPORT Port,
BOOLEAN MemoryMapped,
UCHAR AccessSize,
UCHAR BitWidth )
93{
94 UNREFERENCED_PARAMETER(AccessSize);
95 UNREFERENCED_PARAMETER(BitWidth);
96
97 Port->Flags = 0;
98 return Uart16550InitializePortCommon(LoadOptions,
99 Port,
100 MemoryMapped,
102 32);
103}
BOOLEAN Uart16550InitializePortCommon(_In_opt_ _Null_terminated_ PCHAR LoadOptions, _Inout_ PCPPORT Port, BOOLEAN MemoryMapped, UCHAR AccessSize, UCHAR BitWidth)
Definition uart16550.c:137
@ AcpiGenericAccessSizeByte
Definition uartp.h:51

◆ Apm88xxxxSetBaud()

BOOLEAN Apm88xxxxSetBaud ( _Inout_ PCPPORT Port,
ULONG Rate )
128{
129 if (CHECK_FLAG(Port->Flags, PORT_DEFAULT_RATE))
130 {
131 return FALSE;
132 }
133
134 //
135 // N.B. The CLOCK_RATE defined in this file is different from the one
136 // used by Uart16550SetBaud.
137 //
138
139 return Uart16550SetBaudCommon(Port, Rate, CLOCK_RATE);
140}
#define FALSE
Definition BasicTypes.h:54
BOOLEAN Uart16550SetBaudCommon(_Inout_ PCPPORT Port, ULONG Rate, ULONG Clock)
Definition uart16550.c:436
#define CLOCK_RATE
Definition apm88xxxx.c:24
#define CHECK_FLAG(_x, _f)
Definition uartp.h:27

◆ Uart16550GetByte()

UART_STATUS Uart16550GetByte ( _Inout_ PCPPORT Port,
_Out_ PUCHAR Byte )
568{
569 UCHAR Data;
570 UCHAR Lsr;
571 UCHAR Msr;
572
573 *Byte = 0;
574
575 if ((Port == NULL) || (Port->Address == NULL))
576 {
577 return UartNotReady;
578 }
579
580 //
581 // Check to see if all bits are set in LSR. If this is the case, it means
582 // the port I/O address is invalid as 0xFF is nonsense for LSR.
583 //
584
585 Lsr = Port->Read(Port, COM_LSR);
586 if (Lsr == SERIAL_LSR_NOT_PRESENT)
587 {
588 return UartNotReady;
589 }
590
591 if (CHECK_FLAG(Lsr, COM_DATRDY))
592 {
593 //
594 // Return unsuccessfully if any errors are indicated by the
595 // LSR.
596 //
597
598 if (CHECK_FLAG(Lsr, COM_PE) ||
599 CHECK_FLAG(Lsr, COM_FE) ||
600 CHECK_FLAG(Lsr, COM_OE))
601 {
602 return UartError;
603 }
604
605 Data = Port->Read(Port, COM_DAT);
606
607 //
608 // When using modem control, ignore any bytes that don't have
609 // the carrier detect flag set.
610 //
611
612 if (CHECK_FLAG(Port->Flags, PORT_MODEM_CONTROL))
613 {
614 Msr = Port->Read(Port, COM_MSR);
615 if (CHECK_FLAG(Msr, MS_CD) == FALSE)
616 {
617 return UartNoData;
618 }
619 }
620
621 *Byte = Data;
622 return UartSuccess;
623 }
624 else
625 {
626 //
627 // Data is not available. Determine if the ring indicator has toggled.
628 // If so, enable modem control.
629 //
630
631 Msr = Port->Read(Port, COM_MSR);
632 if ((CHECK_FLAG(Port->Flags, PORT_RING_INDICATOR) &&
633 !CHECK_FLAG(Msr, SERIAL_MSR_RI)) ||
634 (!CHECK_FLAG(Port->Flags, PORT_RING_INDICATOR) &&
636 {
637 Port->Flags |= PORT_MODEM_CONTROL;
638 }
639
640 return UartNoData;
641 }
642}
unsigned char UCHAR
Definition BasicTypes.h:35
#define COM_LSR
Definition kdcom.h:36
#define COM_PE
Definition kdcom.h:44
#define COM_FE
Definition kdcom.h:43
#define COM_OE
Definition kdcom.h:45
#define COM_MSR
Definition kdcom.h:37
#define SERIAL_MSR_RI
Definition kdcom.h:107
#define COM_DATRDY
Definition kdcom.h:60
#define COM_DAT
Definition kdcom.h:31
#define MS_CD
Definition kdcom.h:53
#define SERIAL_LSR_NOT_PRESENT
Definition kdcom.h:116
Start of Optional Data
Definition script_buffer.hex.txt:8

◆ Uart16550InitializePortCommon()

BOOLEAN Uart16550InitializePortCommon ( _In_opt_ _Null_terminated_ PCHAR LoadOptions,
_Inout_ PCPPORT Port,
BOOLEAN MemoryMapped,
UCHAR AccessSize,
UCHAR BitWidth )
171{
172 UCHAR RegisterValue;
173
174 UNREFERENCED_PARAMETER(LoadOptions);
175
176 //
177 // Set the Read / Write function pointers for this serial port.
178 //
179
180 UartpSetAccess(Port, MemoryMapped, AccessSize, BitWidth);
181
182 //
183 // Set DLAB to zero. The DLAB controls the meaning of the first two
184 // registers. When zero, the first register is used for all byte transfers
185 // and the second register controls device interrupts.
186 //
187
188 RegisterValue = Port->Read(Port, COM_LCR);
189 RegisterValue &= ~LC_DLAB;
190 Port->Write(Port, COM_LCR, RegisterValue);
191
192 //
193 // Disable device interrupts. This implementation will handle state
194 // transitions by request only.
195 //
196
197 Port->Write(Port, COM_IEN, 0);
198
199 //
200 // Reset and disable the FIFO queue.
201 // N.B. FIFO will be re-enabled before returning from this routine.
202 //
203
204 Port->Write(Port, COM_FCR, FC_CLEAR_TRANSMIT | FC_CLEAR_RECEIVE);
205
206 //
207 // Configure the baud rate and mode.
208 //
209
210 Uart16550SetBaud(Port, Port->BaudRate);
211
212 //
213 // Enable the FIFO.
214 //
215
216 Port->Write(Port, COM_FCR, FC_ENABLE);
217
218 //
219 // Assert DTR, RTS. Disable loopback. Indicate to the device that
220 // we are able to send and receive data.
221 //
222
223 Port->Write(Port, COM_MCR, MC_DTRRTS);
224
225 //
226 // Initialize ring indicator bit based on hardware state.
227 //
228
229 RegisterValue = Port->Read(Port, COM_MSR);
230 if (CHECK_FLAG(RegisterValue, SERIAL_MSR_RI))
231 {
232 Port->Flags |= PORT_RING_INDICATOR;
233 }
234
235 return TRUE;
236}
#define TRUE
Definition BasicTypes.h:55
#define FC_CLEAR_TRANSMIT
Definition kdcom.h:57
#define FC_CLEAR_RECEIVE
Definition kdcom.h:56
#define COM_IEN
Definition kdcom.h:32
#define FC_ENABLE
Definition kdcom.h:55
#define MC_DTRRTS
Definition kdcom.h:51
#define COM_MCR
Definition kdcom.h:35
#define COM_FCR
Definition kdcom.h:33
#define COM_LCR
Definition kdcom.h:34
BOOLEAN Uart16550SetBaud(_Inout_ PCPPORT Port, ULONG Rate)
Definition uart16550.c:514
BOOLEAN UartpSetAccess(_Inout_ PCPPORT Port, const BOOLEAN MemoryMapped, const UCHAR AccessSize, const UCHAR BitWidth)
Definition uartio.c:225

◆ Uart16550PutByte()

UART_STATUS Uart16550PutByte ( _Inout_ PCPPORT Port,
UCHAR Byte,
BOOLEAN BusyWait )
667{
668 UCHAR Lsr;
669 UCHAR Msr;
670
671 if ((Port == NULL) || (Port->Address == NULL))
672 {
673 return UartNotReady;
674 }
675
676 //
677 // When using modem control, DSR, CTS, and CD flags must all be set before
678 // sending any data.
679 //
680
681 if (CHECK_FLAG(Port->Flags, PORT_MODEM_CONTROL))
682 {
683 Msr = Port->Read(Port, COM_MSR);
684 while ((Msr & MS_DSRCTSCD) != MS_DSRCTSCD)
685 {
686 //
687 // If there's a byte ready, discard it from the input queue.
688 //
689
690 if (!CHECK_FLAG(Msr, MS_CD))
691 {
692 Lsr = Port->Read(Port, COM_LSR);
693 if (CHECK_FLAG(Port->Flags, COM_DATRDY))
694 {
695 Port->Read(Port, COM_DAT);
696 }
697 }
698
699 Msr = Port->Read(Port, COM_MSR);
700 }
701 }
702
703 //
704 // Check to see if all bits are set in LSR. If this is the case, it means
705 // the port I/O address is invalid as 0xFF is nonsense for LSR. This
706 // prevents writing a byte to non-existent hardware.
707 //
708
709 Lsr = Port->Read(Port, COM_LSR);
710 if (Lsr == SERIAL_LSR_NOT_PRESENT)
711 {
712 return UartNotReady;
713 }
714
715 //
716 // The port must be ready to accept a byte for output before continuing.
717 //
718
719 while (!CHECK_FLAG(Lsr, COM_OUTRDY))
720 {
721 //
722 // Determine if the ring indicator has toggled.
723 // If so, enable modem control.
724 //
725
726 Msr = Port->Read(Port, COM_MSR);
727 if ((CHECK_FLAG(Port->Flags, PORT_RING_INDICATOR) &&
728 !CHECK_FLAG(Msr, SERIAL_MSR_RI)) ||
729 (!CHECK_FLAG(Port->Flags, PORT_RING_INDICATOR) &&
731 {
732 Port->Flags |= PORT_MODEM_CONTROL;
733 }
734
735 if (BusyWait == FALSE)
736 {
737 return UartNotReady;
738 }
739
740 Lsr = Port->Read(Port, COM_LSR);
741 }
742
743 //
744 // Transmitter holding register is empty. Send the byte.
745 //
746
747 Port->Write(Port, COM_DAT, Byte);
748 return UartSuccess;
749}
#define MS_DSRCTSCD
Definition kdcom.h:52
#define COM_OUTRDY
Definition kdcom.h:59

◆ Uart16550RxReady()

BOOLEAN Uart16550RxReady ( _Inout_ PCPPORT Port)
771{
772 UCHAR Lsr;
773
774 if ((Port == NULL) || (Port->Address == NULL))
775 {
776 return FALSE;
777 }
778
779 //
780 // Check to see if all bits are set in LSR. If this is the case, it means
781 // the port I/O address is invalid as 0xFF is nonsense for LSR. This
782 // prevents the DATRDY check below from returning TRUE, which could cause
783 // a caller to think that data is pending when in actuality there is no
784 // UART present.
785 //
786
787 Lsr = Port->Read(Port, COM_LSR);
788 if (Lsr == SERIAL_LSR_NOT_PRESENT)
789 {
790 return FALSE;
791 }
792
793 //
794 // Look at the Line Status Register to determine if there is pending data.
795 //
796
797 if (CHECK_FLAG(Lsr, COM_DATRDY))
798 {
799 return TRUE;
800 }
801
802 return FALSE;
803}

◆ Uart16550SetBaudCommon()

BOOLEAN Uart16550SetBaudCommon ( _Inout_ PCPPORT Port,
ULONG Rate,
ULONG Clock )
461{
462 UCHAR Lcr;
463
464 if ((Port == NULL) || (Port->Address == NULL))
465 {
466 return FALSE;
467 }
468
469 if ((Rate == 0) || (Clock == 0))
470 {
471 return FALSE;
472 }
473
474 //
475 // A device's baud rate is written to DLL and DLM. The values of these
476 // registers are the resultant when the max rate (clock) is divided by the
477 // device's desired operating rate.
478 //
479
480 const ULONG DivisorLatch = Clock / Rate;
481
482 //
483 // Set the divisor latch access bit (DLAB) in the line control register.
484 // When non-zero, the first two registers become DLL and DLM.
485 //
486
487 Lcr = Port->Read(Port, COM_LCR);
488 Lcr |= LC_DLAB;
489 Port->Write(Port, COM_LCR, Lcr);
490
491 //
492 // Set the divisor latch value (MSB first, then LSB).
493 //
494
495 Port->Write(Port, COM_DLM, (UCHAR)((DivisorLatch >> 8) & 0xFF));
496 Port->Write(Port, COM_DLL, (UCHAR)(DivisorLatch & 0xFF));
497
498 //
499 // Set Line Control Register to 8N1 (no parity, 8 data bits, 1 stop bit).
500 // This also sets the DLAB back to zero.
501 //
502
503 Port->Write(Port, COM_LCR, 3);
504
505 //
506 // Remember the baud rate.
507 //
508
509 Port->BaudRate = Rate;
510 return TRUE;
511}
unsigned long ULONG
Definition BasicTypes.h:37
#define COM_DLL
Definition kdcom.h:39
#define LC_DLAB
Definition kdcom.h:47
#define COM_DLM
Definition kdcom.h:40

Variable Documentation

◆ Apm88xxxxHardwareDriver

UART_HARDWARE_DRIVER Apm88xxxxHardwareDriver
Initial value:
= {
BOOLEAN Uart16550RxReady(_Inout_ PCPPORT Port)
Definition uart16550.c:752
UART_STATUS Uart16550GetByte(_Inout_ PCPPORT Port, _Out_ PUCHAR Byte)
Definition uart16550.c:546
BOOLEAN Apm88xxxxInitializePort(_In_opt_ _Null_terminated_ PCHAR LoadOptions, _Inout_ PCPPORT Port, BOOLEAN MemoryMapped, UCHAR AccessSize, UCHAR BitWidth)
Definition apm88xxxx.c:60
BOOLEAN Apm88xxxxSetBaud(_Inout_ PCPPORT Port, ULONG Rate)
Definition apm88xxxx.c:106
UART_STATUS Uart16550PutByte(_Inout_ PCPPORT Port, UCHAR Byte, BOOLEAN BusyWait)
Definition uart16550.c:645