I’m trying to use the serial port (COM) to send/receive data over the serial device in order to make a new kernel debugger for Windows.
Actually, it’s not possible to use NT APIs for this purpose, it’s because I want to halt the system by raising the IRQL and masking the interrupts and also want to use the serial port in polling mode.
I use the following code to initialize the serial port.
VOID CpInitialize( PCPPORT Port, PUCHAR Address, ULONG Rate)
{
PUCHAR hwport;
UCHAR mcr, ier;
Port->Address = Address;
Port->Baud = 0;
CpSetBaud(Port, Rate);
// Assert DTR, RTS.
hwport = Port->Address;
hwport += COM_MCR;
mcr = MC_DTRRTS;
_outp(hwport, mcr);
hwport = Port->Address;
hwport += COM_IEN;
ier = 0;
_outp(hwport, ier);
}
and pass 115200 as Rate and COM2_PORT as the Address.
#define COM1_PORT 0x03f8
#define COM2_PORT 0x02f8
#define COM3_PORT 0x03e8
#define COM4_PORT 0x02e8
And finally, for sending a byte out, I use the following function.
VOID CpPutByte(PCPPORT Port, UCHAR Byte)
{
if (KdDbgPortsPresent == FALSE) {
return;
}
// Wait for port to not be busy
while (!(CpReadLsr(Port, COM_OUTRDY) & COM_OUTRDY));
// Send the byte
_outp(Port->Address + COM_DAT, Byte);
}
In order to test the above functions, I create a Serial Device in VMWare Workstation and connect to the Windbg debugger using kdnet. (I don’t use COM for debugging of Windbg.).
The problem is nothing transfers to the other side but if use I a usermode applications then I can successfully transfer data over the serial but it’s not possible to send bytes over serial using the above code.
I further investigated the problem and find a sample from Microsoft in SDK which is called “kdserial”.
After using the “kdserial” codes, I have the exact same problem and tracing into the code, I find that here is the guilty code :
// Check to see if all bits are set in LSR. If this is the case, it means
// the port I/O address is invalid as 0xFF is nonsense for LSR. This
// prevents writing a byte to non-existent hardware.
Lsr = Port->Read(Port, COM_LSR);
if (Lsr == SERIAL_LSR_NOT_PRESENT) {
return UartNotReady;
}
It seems that the port is not initialized as the LSR shows “SERIAL_LSR_NOT_PRESENT=0xff”.
.
.
So, my questions are :
1. According to what I read, Serial ports are I/O mapped and not Memory Mapped I/O (MMIO). Am I right?
2. The second question is, what’s wrong with my code that makes LSR, 0xff, and I can’t send data over this serial port? Did I miss anything?