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