Reactos
at master 356 lines 8.7 kB view raw
1/* 2 * COPYRIGHT: GPL, see COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: drivers/base/kddll/kdcom.c 5 * PURPOSE: COM port functions for the kernel debugger. 6 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) 7 */ 8 9#include "kddll.h" 10 11#include <cportlib/cportlib.h> 12#include <arc/arc.h> 13#include <stdio.h> 14#include <stdlib.h> 15#include <ndk/halfuncs.h> 16 17/* Serial debug connection */ 18#if defined(SARCH_PC98) 19#define DEFAULT_DEBUG_PORT 2 /* COM2 */ 20#define DEFAULT_DEBUG_COM1_IRQ 4 21#define DEFAULT_DEBUG_COM2_IRQ 5 22#define DEFAULT_DEBUG_BAUD_RATE 9600 23#define DEFAULT_BAUD_RATE 9600 24#else 25#define DEFAULT_DEBUG_PORT 2 /* COM2 */ 26#define DEFAULT_DEBUG_COM1_IRQ 4 27#define DEFAULT_DEBUG_COM2_IRQ 3 28#define DEFAULT_DEBUG_BAUD_RATE 115200 29#define DEFAULT_BAUD_RATE 19200 30#endif 31 32#if defined(_M_IX86) || defined(_M_AMD64) 33#if defined(SARCH_PC98) 34const ULONG BaseArray[] = {0, 0x30, 0x238}; 35#else 36const ULONG BaseArray[] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8}; 37#endif 38#elif defined(_M_PPC) 39const ULONG BaseArray[] = {0, 0x800003F8}; 40#elif defined(_M_MIPS) 41const ULONG BaseArray[] = {0, 0x80006000, 0x80007000}; 42#elif defined(_M_ARM) 43const ULONG BaseArray[] = {0, 0xF1012000}; 44#else 45#error Unknown architecture 46#endif 47 48#define MAX_COM_PORTS (sizeof(BaseArray) / sizeof(BaseArray[0]) - 1) 49 50/* GLOBALS ********************************************************************/ 51 52CPPORT KdComPort; 53ULONG KdComPortIrq = 0; // Not used at the moment. 54#ifdef KDDEBUG 55CPPORT KdDebugComPort; 56#endif 57 58/* DEBUGGING ******************************************************************/ 59 60#ifdef KDDEBUG 61ULONG KdpDbgPrint(const char *Format, ...) 62{ 63 va_list ap; 64 int Length; 65 char* ptr; 66 CHAR Buffer[512]; 67 68 va_start(ap, Format); 69 Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap); 70 va_end(ap); 71 72 /* Check if we went past the buffer */ 73 if (Length == -1) 74 { 75 /* Terminate it if we went over-board */ 76 Buffer[sizeof(Buffer) - 1] = '\n'; 77 78 /* Put maximum */ 79 Length = sizeof(Buffer); 80 } 81 82 ptr = Buffer; 83 while (Length--) 84 { 85 if (*ptr == '\n') 86 CpPutByte(&KdDebugComPort, '\r'); 87 88 CpPutByte(&KdDebugComPort, *ptr++); 89 } 90 91 return 0; 92} 93#endif 94 95/* FUNCTIONS ******************************************************************/ 96 97NTSTATUS 98NTAPI 99KdD0Transition(VOID) 100{ 101 return STATUS_SUCCESS; 102} 103 104NTSTATUS 105NTAPI 106KdD3Transition(VOID) 107{ 108 return STATUS_SUCCESS; 109} 110 111NTSTATUS 112NTAPI 113KdSave(IN BOOLEAN SleepTransition) 114{ 115 /* Nothing to do on COM ports */ 116 return STATUS_SUCCESS; 117} 118 119NTSTATUS 120NTAPI 121KdRestore(IN BOOLEAN SleepTransition) 122{ 123 /* Nothing to do on COM ports */ 124 return STATUS_SUCCESS; 125} 126 127NTSTATUS 128NTAPI 129KdpPortInitialize(IN ULONG ComPortNumber, 130 IN ULONG ComPortBaudRate) 131{ 132 NTSTATUS Status; 133 134 KDDBGPRINT("KdpPortInitialize, Port = COM%ld\n", ComPortNumber); 135 136 Status = CpInitialize(&KdComPort, 137 UlongToPtr(BaseArray[ComPortNumber]), 138 ComPortBaudRate); 139 if (!NT_SUCCESS(Status)) 140 { 141 return STATUS_INVALID_PARAMETER; 142 } 143 else 144 { 145 KdComPortInUse = KdComPort.Address; 146 return STATUS_SUCCESS; 147 } 148} 149 150/****************************************************************************** 151 * \name KdDebuggerInitialize0 152 * \brief Phase 0 initialization. 153 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL. 154 * \return Status 155 */ 156NTSTATUS 157NTAPI 158KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL) 159{ 160 ULONG ComPortNumber = DEFAULT_DEBUG_PORT; 161 ULONG ComPortBaudRate = DEFAULT_DEBUG_BAUD_RATE; 162 163 PCHAR CommandLine, PortString, BaudString, IrqString; 164 ULONG Value; 165 166 /* Check if we have a LoaderBlock */ 167 if (LoaderBlock) 168 { 169 /* Get the Command Line */ 170 CommandLine = LoaderBlock->LoadOptions; 171 172 /* Upcase it */ 173 _strupr(CommandLine); 174 175 /* Get the port and baud rate */ 176 PortString = strstr(CommandLine, "DEBUGPORT"); 177 BaudString = strstr(CommandLine, "BAUDRATE"); 178 IrqString = strstr(CommandLine, "IRQ"); 179 180 /* Check if we got the /DEBUGPORT parameter */ 181 if (PortString) 182 { 183 /* Move past the actual string, to reach the port*/ 184 PortString += strlen("DEBUGPORT"); 185 186 /* Now get past any spaces and skip the equal sign */ 187 while (*PortString == ' ') PortString++; 188 PortString++; 189 190 /* Do we have a serial port? */ 191 if (strncmp(PortString, "COM", 3) != 0) 192 { 193 return STATUS_INVALID_PARAMETER; 194 } 195 196 /* Check for a valid Serial Port */ 197 PortString += 3; 198 Value = atol(PortString); 199 if (Value >= sizeof(BaseArray) / sizeof(BaseArray[0])) 200 { 201 return STATUS_INVALID_PARAMETER; 202 } 203 204 /* Set the port to use */ 205 ComPortNumber = Value; 206 } 207 208 /* Check if we got a baud rate */ 209 if (BaudString) 210 { 211 /* Move past the actual string, to reach the rate */ 212 BaudString += strlen("BAUDRATE"); 213 214 /* Now get past any spaces */ 215 while (*BaudString == ' ') BaudString++; 216 217 /* And make sure we have a rate */ 218 if (*BaudString) 219 { 220 /* Read and set it */ 221 Value = atol(BaudString + 1); 222 if (Value) ComPortBaudRate = Value; 223 } 224 } 225 226 /* Check Serial Port Settings [IRQ] */ 227 if (IrqString) 228 { 229 /* Move past the actual string, to reach the rate */ 230 IrqString += strlen("IRQ"); 231 232 /* Now get past any spaces */ 233 while (*IrqString == ' ') IrqString++; 234 235 /* And make sure we have an IRQ */ 236 if (*IrqString) 237 { 238 /* Read and set it */ 239 Value = atol(IrqString + 1); 240 if (Value) KdComPortIrq = Value; 241 } 242 } 243 } 244 245#ifdef KDDEBUG 246 /* 247 * Try to find a free COM port and use it as the KD debugging port. 248 * NOTE: Inspired by reactos/boot/freeldr/freeldr/comm/rs232.c, Rs232PortInitialize(...) 249 */ 250 { 251 /* 252 * Start enumerating COM ports from the last one to the first one, 253 * and break when we find a valid port. 254 * If we reach the first element of the list, the invalid COM port, 255 * then it means that no valid port was found. 256 */ 257 ULONG ComPort; 258 for (ComPort = MAX_COM_PORTS; ComPort > 0; ComPort--) 259 { 260 /* Check if the port exist; skip the KD port */ 261 if ((ComPort != ComPortNumber) && CpDoesPortExist(UlongToPtr(BaseArray[ComPort]))) 262 break; 263 } 264 if (ComPort != 0) 265 CpInitialize(&KdDebugComPort, UlongToPtr(BaseArray[ComPort]), DEFAULT_BAUD_RATE); 266 } 267#endif 268 269 KDDBGPRINT("KdDebuggerInitialize0\n"); 270 271 /* Initialize the port */ 272 return KdpPortInitialize(ComPortNumber, ComPortBaudRate); 273} 274 275/****************************************************************************** 276 * \name KdDebuggerInitialize1 277 * \brief Phase 1 initialization. 278 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL. 279 * \return Status 280 */ 281NTSTATUS 282NTAPI 283KdDebuggerInitialize1(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL) 284{ 285 return STATUS_SUCCESS; 286} 287 288 289VOID 290NTAPI 291KdpSendByte(IN UCHAR Byte) 292{ 293 /* Send the byte */ 294 CpPutByte(&KdComPort, Byte); 295} 296 297KDP_STATUS 298NTAPI 299KdpPollByte(OUT PUCHAR OutByte) 300{ 301 USHORT Status; 302 303 /* Poll the byte */ 304 Status = CpGetByte(&KdComPort, OutByte, FALSE, FALSE); 305 switch (Status) 306 { 307 case CP_GET_SUCCESS: 308 return KDP_PACKET_RECEIVED; 309 310 case CP_GET_NODATA: 311 return KDP_PACKET_TIMEOUT; 312 313 case CP_GET_ERROR: 314 default: 315 return KDP_PACKET_RESEND; 316 } 317} 318 319KDP_STATUS 320NTAPI 321KdpReceiveByte(OUT PUCHAR OutByte) 322{ 323 USHORT Status; 324 325 /* Get the byte */ 326 Status = CpGetByte(&KdComPort, OutByte, TRUE, FALSE); 327 switch (Status) 328 { 329 case CP_GET_SUCCESS: 330 return KDP_PACKET_RECEIVED; 331 332 case CP_GET_NODATA: 333 return KDP_PACKET_TIMEOUT; 334 335 case CP_GET_ERROR: 336 default: 337 return KDP_PACKET_RESEND; 338 } 339} 340 341KDP_STATUS 342NTAPI 343KdpPollBreakIn(VOID) 344{ 345 KDP_STATUS KdStatus; 346 UCHAR Byte; 347 348 KdStatus = KdpPollByte(&Byte); 349 if ((KdStatus == KDP_PACKET_RECEIVED) && (Byte == BREAKIN_PACKET_BYTE)) 350 { 351 return KDP_PACKET_RECEIVED; 352 } 353 return KDP_PACKET_TIMEOUT; 354} 355 356/* EOF */