/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/hal/x86/kdbg.c * PURPOSE: Serial i/o functions for the kernel debugger. * PROGRAMMER: Emanuele Aliberti * Eric Kohl * UPDATE HISTORY: * Created 05/09/99 */ /* INCLUDES *****************************************************************/ #include #define NDEBUG #include #define DEFAULT_BAUD_RATE 19200 /* MACROS *******************************************************************/ #define SER_RBR(x) ((x)+0) #define SER_THR(x) ((x)+0) #define SER_DLL(x) ((x)+0) #define SER_IER(x) ((x)+1) #define SR_IER_ERDA 0x01 #define SR_IER_ETHRE 0x02 #define SR_IER_ERLSI 0x04 #define SR_IER_EMS 0x08 #define SR_IER_ALL 0x0F #define SER_DLM(x) ((x)+1) #define SER_IIR(x) ((x)+2) #define SER_LCR(x) ((x)+3) #define SR_LCR_CS5 0x00 #define SR_LCR_CS6 0x01 #define SR_LCR_CS7 0x02 #define SR_LCR_CS8 0x03 #define SR_LCR_ST1 0x00 #define SR_LCR_ST2 0x04 #define SR_LCR_PNO 0x00 #define SR_LCR_POD 0x08 #define SR_LCR_PEV 0x18 #define SR_LCR_PMK 0x28 #define SR_LCR_PSP 0x38 #define SR_LCR_BRK 0x40 #define SR_LCR_DLAB 0x80 #define SER_MCR(x) ((x)+4) #define SR_MCR_DTR 0x01 #define SR_MCR_RTS 0x02 #define SR_MCR_OUT1 0x04 #define SR_MCR_OUT2 0x08 #define SR_MCR_LOOP 0x10 #define SER_LSR(x) ((x)+5) #define SR_LSR_DR 0x01 #define SR_LSR_TBE 0x20 #define SER_MSR(x) ((x)+6) #define SR_MSR_CTS 0x10 #define SR_MSR_DSR 0x20 #define SER_SCR(x) ((x)+7) /* GLOBAL VARIABLES *********************************************************/ ULONG EXPORTED KdComPortInUse = 0; /* STATIC VARIABLES *********************************************************/ static ULONG ComPort = 0; static ULONG BaudRate = 0; static PUCHAR PortBase = (PUCHAR)0; /* The com port must only be initialized once! */ static BOOLEAN PortInitialized = FALSE; /* STATIC FUNCTIONS *********************************************************/ static BOOLEAN KdpDoesComPortExist (PUCHAR BaseAddress) { BOOLEAN found; BYTE mcr; BYTE msr; found = FALSE; /* save Modem Control Register (MCR) */ mcr = READ_PORT_UCHAR (SER_MCR(BaseAddress)); /* enable loop mode (set Bit 4 of the MCR) */ WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x10); /* clear all modem output bits */ WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x10); /* read the Modem Status Register */ msr = READ_PORT_UCHAR (SER_MSR(BaseAddress)); /* * the upper nibble of the MSR (modem output bits) must be * equal to the lower nibble of the MCR (modem input bits) */ if ((msr & 0xF0) == 0x00) { /* set all modem output bits */ WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x1F); /* read the Modem Status Register */ msr = READ_PORT_UCHAR (SER_MSR(BaseAddress)); /* * the upper nibble of the MSR (modem output bits) must be * equal to the lower nibble of the MCR (modem input bits) */ if ((msr & 0xF0) == 0xF0) found = TRUE; } /* restore MCR */ WRITE_PORT_UCHAR (SER_MCR(BaseAddress), mcr); return (found); } /* FUNCTIONS ****************************************************************/ /* HAL.KdPortInitialize */ BOOLEAN STDCALL KdPortInitialize ( PKD_PORT_INFORMATION PortInformation, DWORD Unknown1, DWORD Unknown2 ) { ULONG BaseArray[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8}; char buffer[80]; ULONG divisor; BYTE lcr; if (PortInitialized == FALSE) { if (PortInformation->BaudRate != 0) { BaudRate = PortInformation->BaudRate; } else { BaudRate = DEFAULT_BAUD_RATE; } if (PortInformation->ComPort == 0) { if (KdpDoesComPortExist ((PUCHAR)BaseArray[2])) { PortBase = (PUCHAR)BaseArray[2]; ComPort = 2; PortInformation->BaseAddress = (ULONG)PortBase; PortInformation->ComPort = ComPort; #ifndef NDEBUG sprintf (buffer, "\nSerial port COM%ld found at 0x%lx\n", ComPort, (ULONG)PortBase); HalDisplayString (buffer); #endif /* NDEBUG */ } else if (KdpDoesComPortExist ((PUCHAR)BaseArray[1])) { PortBase = (PUCHAR)BaseArray[1]; ComPort = 1; PortInformation->BaseAddress = (ULONG)PortBase; PortInformation->ComPort = ComPort; #ifndef NDEBUG sprintf (buffer, "\nSerial port COM%ld found at 0x%lx\n", ComPort, (ULONG)PortBase); HalDisplayString (buffer); #endif /* NDEBUG */ } else { sprintf (buffer, "\nKernel Debugger: No COM port found!!!\n\n"); HalDisplayString (buffer); return FALSE; } } else { if (KdpDoesComPortExist ((PUCHAR)BaseArray[PortInformation->ComPort])) { PortBase = (PUCHAR)BaseArray[PortInformation->ComPort]; ComPort = PortInformation->ComPort; PortInformation->BaseAddress = (ULONG)PortBase; #ifndef NDEBUG sprintf (buffer, "\nSerial port COM%ld found at 0x%lx\n", ComPort, (ULONG)PortBase); HalDisplayString (buffer); #endif /* NDEBUG */ } else { sprintf (buffer, "\nKernel Debugger: No serial port found!!!\n\n"); HalDisplayString (buffer); return FALSE; } } PortInitialized = TRUE; } /* * set baud rate and data format (8N1) */ /* turn on DTR and RTS */ WRITE_PORT_UCHAR (SER_MCR(PortBase), SR_MCR_DTR | SR_MCR_RTS); /* set DLAB */ lcr = READ_PORT_UCHAR (SER_LCR(PortBase)) | SR_LCR_DLAB; WRITE_PORT_UCHAR (SER_LCR(PortBase), lcr); /* set baud rate */ divisor = 115200 / BaudRate; WRITE_PORT_UCHAR (SER_DLL(PortBase), divisor & 0xff); WRITE_PORT_UCHAR (SER_DLM(PortBase), (divisor >> 8) & 0xff); /* reset DLAB and set 8N1 format */ WRITE_PORT_UCHAR (SER_LCR(PortBase), SR_LCR_CS8 | SR_LCR_ST1 | SR_LCR_PNO); /* read junk out of the RBR */ lcr = READ_PORT_UCHAR (SER_RBR(PortBase)); /* * set global info */ KdComPortInUse = (ULONG)PortBase; /* * print message to blue screen */ sprintf (buffer, "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n", ComPort, (ULONG)PortBase, BaudRate); HalDisplayString (buffer); return TRUE; } /* HAL.KdPortInitializeEx */ BOOLEAN STDCALL KdPortInitializeEx ( PKD_PORT_INFORMATION PortInformation, DWORD Unknown1, DWORD Unknown2 ) { ULONG BaseArray[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8}; PUCHAR ComPortBase; char buffer[80]; ULONG divisor; BYTE lcr; if (PortInformation->BaudRate == 0) { PortInformation->BaudRate = DEFAULT_BAUD_RATE; } if (PortInformation->ComPort == 0) { return FALSE; } else { if (KdpDoesComPortExist ((PUCHAR)BaseArray[PortInformation->ComPort])) { ComPortBase = (PUCHAR)BaseArray[PortInformation->ComPort]; PortInformation->BaseAddress = (ULONG)ComPortBase; #ifndef NDEBUG sprintf (buffer, "\nSerial port COM%ld found at 0x%lx\n", PortInformation->ComPort, (ULONG)ComPortBase]; HalDisplayString (buffer); #endif /* NDEBUG */ } else { sprintf (buffer, "\nKernel Debugger: Serial port not found!!!\n\n"); HalDisplayString (buffer); return FALSE; } } /* * set baud rate and data format (8N1) */ /* turn on DTR and RTS */ WRITE_PORT_UCHAR (SER_MCR(ComPortBase), SR_MCR_DTR | SR_MCR_RTS); /* set DLAB */ lcr = READ_PORT_UCHAR (SER_LCR(ComPortBase)) | SR_LCR_DLAB; WRITE_PORT_UCHAR (SER_LCR(ComPortBase), lcr); /* set baud rate */ divisor = 115200 / PortInformation->BaudRate; WRITE_PORT_UCHAR (SER_DLL(ComPortBase), divisor & 0xff); WRITE_PORT_UCHAR (SER_DLM(ComPortBase), (divisor >> 8) & 0xff); /* reset DLAB and set 8N1 format */ WRITE_PORT_UCHAR (SER_LCR(ComPortBase), SR_LCR_CS8 | SR_LCR_ST1 | SR_LCR_PNO); /* read junk out of the RBR */ lcr = READ_PORT_UCHAR (SER_RBR(ComPortBase)); #ifndef NDEBUG /* * print message to blue screen */ sprintf (buffer, "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n", PortInformation->ComPort, (ULONG)ComPortBase, PortInformation->BaudRate); HalDisplayString (buffer); #endif /* NDEBUG */ return TRUE; } /* HAL.KdPortGetByte */ BOOLEAN STDCALL KdPortGetByte ( PUCHAR ByteRecieved ) { if (PortInitialized == FALSE) return FALSE; if ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_DR)) { *ByteRecieved = READ_PORT_UCHAR (SER_RBR(PortBase)); return TRUE; } return FALSE; } /* HAL.KdPortGetByteEx */ BOOLEAN STDCALL KdPortGetByteEx ( PKD_PORT_INFORMATION PortInformation, PUCHAR ByteRecieved ) { PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress; if ((READ_PORT_UCHAR (SER_LSR(ComPortBase)) & SR_LSR_DR)) { *ByteRecieved = READ_PORT_UCHAR (SER_RBR(ComPortBase)); return TRUE; } return FALSE; } /* HAL.KdPortPollByte */ BOOLEAN STDCALL KdPortPollByte ( PUCHAR ByteRecieved ) { if (PortInitialized == FALSE) return FALSE; while ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_DR) == 0) ; *ByteRecieved = READ_PORT_UCHAR (SER_RBR(PortBase)); return TRUE; } /* HAL.KdPortPollByteEx */ BOOLEAN STDCALL KdPortPollByteEx ( PKD_PORT_INFORMATION PortInformation, PUCHAR ByteRecieved ) { PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress; while ((READ_PORT_UCHAR (SER_LSR(ComPortBase)) & SR_LSR_DR) == 0) ; *ByteRecieved = READ_PORT_UCHAR (SER_RBR(ComPortBase)); return TRUE; } /* HAL.KdPortPutByte */ VOID STDCALL KdPortPutByte ( UCHAR ByteToSend ) { if (PortInitialized == FALSE) return; while ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_TBE) == 0) ; WRITE_PORT_UCHAR (SER_THR(PortBase), ByteToSend); } /* HAL.KdPortPutByteEx */ VOID STDCALL KdPortPutByteEx ( PKD_PORT_INFORMATION PortInformation, UCHAR ByteToSend ) { PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress; while ((READ_PORT_UCHAR (SER_LSR(ComPortBase)) & SR_LSR_TBE) == 0) ; WRITE_PORT_UCHAR (SER_THR(ComPortBase), ByteToSend); } /* HAL.KdPortRestore */ VOID STDCALL KdPortRestore ( VOID ) { } /* HAL.KdPortSave */ VOID STDCALL KdPortSave ( VOID ) { } /* HAL.KdPortDisableInterrupts */ BOOLEAN STDCALL KdPortDisableInterrupts() { UCHAR ch; if (PortInitialized == FALSE) return FALSE; ch = READ_PORT_UCHAR (SER_MCR (PortBase)); ch &= (~(SR_MCR_OUT1 | SR_MCR_OUT2)); WRITE_PORT_UCHAR (SER_MCR (PortBase), ch); ch = READ_PORT_UCHAR (SER_IER (PortBase)); ch &= (~SR_IER_ALL); WRITE_PORT_UCHAR (SER_IER (PortBase), ch); return TRUE; } /* HAL.KdPortEnableInterrupts */ BOOLEAN STDCALL KdPortEnableInterrupts() { UCHAR ch; if (PortInitialized == FALSE) return FALSE; ch = READ_PORT_UCHAR (SER_IER (PortBase)); ch &= (~SR_IER_ALL); ch |= SR_IER_ERDA; WRITE_PORT_UCHAR (SER_IER (PortBase), ch); ch = READ_PORT_UCHAR (SER_MCR (PortBase)); ch &= (~SR_MCR_LOOP); ch |= (SR_MCR_OUT1 | SR_MCR_OUT2); WRITE_PORT_UCHAR (SER_MCR (PortBase), ch); return TRUE; } /* EOF */