| [354] | 1 | /* SCCSID = %W% %E% */
|
|---|
| 2 | /****************************************************************************
|
|---|
| 3 | * *
|
|---|
| 4 | * Copyright (c) IBM Corporation 1994 - 1997. *
|
|---|
| 5 | * *
|
|---|
| 6 | * The following IBM OS/2 source code is provided to you solely for the *
|
|---|
| 7 | * the purpose of assisting you in your development of OS/2 device drivers. *
|
|---|
| 8 | * You may use this code in accordance with the IBM License Agreement *
|
|---|
| 9 | * provided in the IBM Device Driver Source Kit for OS/2. *
|
|---|
| 10 | * *
|
|---|
| 11 | ****************************************************************************/
|
|---|
| 12 | /**@internal %W%
|
|---|
| 13 | * Facilities for logging errors, status, and realtime traces. Logged
|
|---|
| 14 | * information can be routed to any combination of display, COM: lines,
|
|---|
| 15 | * system trace buffer (retrieved by TRACEFMT utility), and/or system
|
|---|
| 16 | * error log.
|
|---|
| 17 | * @version %I%
|
|---|
| 18 | * @context 16-bit, Ring 3 or Ring 0, DD Ioctl time context. The BINARYLOG
|
|---|
| 19 | * and PERFLOG methods may be used in Interrupt context.
|
|---|
| 20 | * @notes
|
|---|
| 21 | *
|
|---|
| 22 | * Supported syntax for data formatting (case insensitive)
|
|---|
| 23 | *
|
|---|
| 24 | * >--- % --+-----+--------------- B -+---|
|
|---|
| 25 | * | | | |
|
|---|
| 26 | * +- 0 -+ +----------- Q -+
|
|---|
| 27 | * | |
|
|---|
| 28 | * +-----+---+- D -+
|
|---|
| 29 | * | | | |
|
|---|
| 30 | * +- L -+ +- X -+
|
|---|
| 31 | *
|
|---|
| 32 | * Where
|
|---|
| 33 | * 0 - format with leading 0's
|
|---|
| 34 | * L - long integer
|
|---|
| 35 | * D - format decimal
|
|---|
| 36 | * X - format hexidecimal
|
|---|
| 37 | * B - byte hex (BINARY logs only)
|
|---|
| 38 | * Q - quadword hex (BINARY logs only)
|
|---|
| 39 | * Not supported at this time
|
|---|
| 40 | * S - ASCIIZ data
|
|---|
| 41 | *
|
|---|
| 42 | * @notes bugs
|
|---|
| 43 | * The %b, %q, and %b datatypes are not implemented across all log types.
|
|---|
| 44 | *
|
|---|
| 45 | * @history
|
|---|
| 46 | */
|
|---|
| 47 |
|
|---|
| 48 | extern "C" {
|
|---|
| 49 | #define INCL_NOPMAPI
|
|---|
| 50 | #define INCL_DOSMISC
|
|---|
| 51 | #include <os2.h>
|
|---|
| 52 | }
|
|---|
| 53 |
|
|---|
| 54 | #include <devhelp.h>
|
|---|
| 55 | #include <string.h> // strlen() intrinsic
|
|---|
| 56 | #include "iodelay.h"
|
|---|
| 57 | #include "log.hpp"
|
|---|
| 58 | #include <include.h>
|
|---|
| 59 |
|
|---|
| 60 | #define CR 0x0d
|
|---|
| 61 | #define LF 0x0a
|
|---|
| 62 |
|
|---|
| 63 | #define LEADING_ZEROES 0x8000
|
|---|
| 64 | #define SIGNIFICANT_FIELD 0x0007
|
|---|
| 65 |
|
|---|
| 66 | #define UART_DATA 0x00 // UART Data port
|
|---|
| 67 | #define UART_INT_ENAB 0x01 // UART Interrupt enable
|
|---|
| 68 | #define UART_INT_ID 0x02 // interrupt ID
|
|---|
| 69 | #define UART_LINE_CTRL 0x03 // line control registers
|
|---|
| 70 | #define UART_MODEM_CTRL 0x04 // modem control register
|
|---|
| 71 | #define UART_LINE_STAT 0x05 // line status register
|
|---|
| 72 | #define UART_MODEM_STAT 0x06 // modem status regiser
|
|---|
| 73 | #define UART_DIVISOR_LO 0x00 // divisor latch least sig
|
|---|
| 74 | #define UART_DIVISOR_HI 0x01h // divisor latch most sig
|
|---|
| 75 |
|
|---|
| 76 | // Global logging variables. Values are setup in init.cpp.
|
|---|
| 77 | LOG* pStatus; // Points to the status log.
|
|---|
| 78 | LOG* pError; // Points to the error log.
|
|---|
| 79 | LOG* pSoftError; // Points to the error log.
|
|---|
| 80 | BINARYLOG* pTrace; // Points to the trace log.
|
|---|
| 81 | PERFLOG* pPerfLog; // Points to Performance trace log.
|
|---|
| 82 |
|
|---|
| 83 | // Used to convert binary to ascii
|
|---|
| 84 | static const char ddhextab[]="0123456789ABCDEF";
|
|---|
| 85 |
|
|---|
| 86 |
|
|---|
| 87 | //----------- ddprintf_DecWordToASCII -
|
|---|
| 88 | PSZ LOG::_DecWordToASCII(PSZ StrPtr, WORD wDecVal, WORD Option)
|
|---|
| 89 | /*
|
|---|
| 90 | ; StrPtr - Output, pointer to location to save resulting ASCII string.
|
|---|
| 91 | ; wDecVal - Input, 16 bit value to convert.
|
|---|
| 92 | ; Option - Input, selects leading zeros.
|
|---|
| 93 | */
|
|---|
| 94 | {
|
|---|
| 95 | BOOL fNonZero=FALSE;
|
|---|
| 96 | WORD Digit;
|
|---|
| 97 | WORD Power=10000;
|
|---|
| 98 |
|
|---|
| 99 | while (Power)
|
|---|
| 100 | {
|
|---|
| 101 | Digit=0;
|
|---|
| 102 | while (wDecVal >=Power) //Digit=wDecVal/Power;
|
|---|
| 103 | {
|
|---|
| 104 | Digit++;
|
|---|
| 105 | wDecVal-=Power;
|
|---|
| 106 | }
|
|---|
| 107 |
|
|---|
| 108 | if (Digit)
|
|---|
| 109 | fNonZero=TRUE;
|
|---|
| 110 |
|
|---|
| 111 | if (Digit ||
|
|---|
| 112 | fNonZero ||
|
|---|
| 113 | (Option & LEADING_ZEROES) ||
|
|---|
| 114 | ((Power==1) && (fNonZero==FALSE)))
|
|---|
| 115 | {
|
|---|
| 116 | *StrPtr=(char)('0'+Digit);
|
|---|
| 117 | StrPtr++;
|
|---|
| 118 | }
|
|---|
| 119 |
|
|---|
| 120 | if (Power==10000)
|
|---|
| 121 | Power=1000;
|
|---|
| 122 | else if (Power==1000)
|
|---|
| 123 | Power=100;
|
|---|
| 124 | else if (Power==100)
|
|---|
| 125 | Power=10;
|
|---|
| 126 | else if (Power==10)
|
|---|
| 127 | Power=1;
|
|---|
| 128 | else
|
|---|
| 129 | Power=0;
|
|---|
| 130 | } // end while
|
|---|
| 131 |
|
|---|
| 132 | return (StrPtr);
|
|---|
| 133 | }
|
|---|
| 134 |
|
|---|
| 135 | //----------- ddprintf_DecLongToASCII -
|
|---|
| 136 | PSZ LOG::_DecLongToASCII(PSZ StrPtr, DWORD lDecVal,WORD Option)
|
|---|
| 137 | {
|
|---|
| 138 | BOOL fNonZero=FALSE;
|
|---|
| 139 | DWORD Digit;
|
|---|
| 140 | DWORD Power=1000000000; // 1 billion
|
|---|
| 141 |
|
|---|
| 142 | while (Power)
|
|---|
| 143 | {
|
|---|
| 144 | Digit=0; // Digit=lDecVal/Power
|
|---|
| 145 | while (lDecVal >=Power) // replaced with while loop
|
|---|
| 146 | {
|
|---|
| 147 | Digit++;
|
|---|
| 148 | lDecVal-=Power;
|
|---|
| 149 | }
|
|---|
| 150 |
|
|---|
| 151 | if (Digit)
|
|---|
| 152 | fNonZero=TRUE;
|
|---|
| 153 |
|
|---|
| 154 | if (Digit ||
|
|---|
| 155 | fNonZero ||
|
|---|
| 156 | (Option & LEADING_ZEROES) ||
|
|---|
| 157 | ((Power==1) && (fNonZero==FALSE)))
|
|---|
| 158 | {
|
|---|
| 159 | *StrPtr=(char)('0'+Digit);
|
|---|
| 160 | StrPtr++;
|
|---|
| 161 | }
|
|---|
| 162 |
|
|---|
| 163 | if (Power==1000000000) // 1 billion
|
|---|
| 164 | Power=100000000;
|
|---|
| 165 | else if (Power==100000000)
|
|---|
| 166 | Power=10000000;
|
|---|
| 167 | else if (Power==10000000)
|
|---|
| 168 | Power=1000000;
|
|---|
| 169 | else if (Power==1000000)
|
|---|
| 170 | Power=100000;
|
|---|
| 171 | else if (Power==100000)
|
|---|
| 172 | Power=10000;
|
|---|
| 173 | else if (Power==10000)
|
|---|
| 174 | Power=1000;
|
|---|
| 175 | else if (Power==1000)
|
|---|
| 176 | Power=100;
|
|---|
| 177 | else if (Power==100)
|
|---|
| 178 | Power=10;
|
|---|
| 179 | else if (Power==10)
|
|---|
| 180 | Power=1;
|
|---|
| 181 | else
|
|---|
| 182 | Power=0;
|
|---|
| 183 | }
|
|---|
| 184 | return (StrPtr);
|
|---|
| 185 | }
|
|---|
| 186 | //----------- ddprintf_HexWordToASCII -
|
|---|
| 187 | PSZ LOG::_HexWordToASCII(PSZ StrPtr, WORD wHexVal, WORD Option)
|
|---|
| 188 | {
|
|---|
| 189 | BOOL fNonZero=FALSE;
|
|---|
| 190 | WORD Digit;
|
|---|
| 191 | WORD Power=0xF000;
|
|---|
| 192 | WORD ShiftVal=12;
|
|---|
| 193 |
|
|---|
| 194 | while (Power)
|
|---|
| 195 | {
|
|---|
| 196 | Digit=(wHexVal & Power)>>ShiftVal;
|
|---|
| 197 | if (Digit)
|
|---|
| 198 | fNonZero=TRUE;
|
|---|
| 199 |
|
|---|
| 200 | if (Digit ||
|
|---|
| 201 | fNonZero ||
|
|---|
| 202 | (Option & LEADING_ZEROES) ||
|
|---|
| 203 | ((Power==0x0F) && (fNonZero==FALSE)))
|
|---|
| 204 | //*StrPtr++=(char)('0'+Digit);
|
|---|
| 205 | *StrPtr++=ddhextab[Digit];
|
|---|
| 206 |
|
|---|
| 207 | Power>>=4;
|
|---|
| 208 | ShiftVal-=4;
|
|---|
| 209 | } // end while
|
|---|
| 210 |
|
|---|
| 211 | return (StrPtr);
|
|---|
| 212 | }
|
|---|
| 213 |
|
|---|
| 214 | //----------- ddprintf_HexLongToASCII -
|
|---|
| 215 | PSZ LOG::_HexLongToASCII( PSZ StrPtr, DWORD wHexVal, WORD Option )
|
|---|
| 216 | {
|
|---|
| 217 | BOOL fNonZero=FALSE;
|
|---|
| 218 | DWORD Digit;
|
|---|
| 219 | DWORD Power=0xF0000000;
|
|---|
| 220 | DWORD ShiftVal=28;
|
|---|
| 221 |
|
|---|
| 222 | while (Power)
|
|---|
| 223 | {
|
|---|
| 224 | Digit=(wHexVal & Power)>>ShiftVal;
|
|---|
| 225 | if (Digit)
|
|---|
| 226 | fNonZero=TRUE;
|
|---|
| 227 |
|
|---|
| 228 | if (Digit ||
|
|---|
| 229 | fNonZero ||
|
|---|
| 230 | (Option & LEADING_ZEROES) ||
|
|---|
| 231 | ((Power==0x0F) && (fNonZero==FALSE)))
|
|---|
| 232 | *StrPtr++=ddhextab[Digit];
|
|---|
| 233 |
|
|---|
| 234 | if (Power==0xF0000000) // 1 billion
|
|---|
| 235 | Power=0xF000000;
|
|---|
| 236 | else if (Power==0xF000000)
|
|---|
| 237 | Power=0xF00000;
|
|---|
| 238 | else if (Power==0xF00000)
|
|---|
| 239 | Power=0xF0000;
|
|---|
| 240 | else if (Power==0xF0000)
|
|---|
| 241 | Power=0xF000;
|
|---|
| 242 | else if (Power==0xF000)
|
|---|
| 243 | Power=0xF00;
|
|---|
| 244 | else if (Power==0xF00)
|
|---|
| 245 | Power=0xF0;
|
|---|
| 246 | else if (Power==0xF0)
|
|---|
| 247 | Power=0xF;
|
|---|
| 248 | else Power=0;
|
|---|
| 249 |
|
|---|
| 250 | ShiftVal-=4;
|
|---|
| 251 | } // end while
|
|---|
| 252 |
|
|---|
| 253 | return (StrPtr);
|
|---|
| 254 | }
|
|---|
| 255 |
|
|---|
| 256 |
|
|---|
| 257 | USHORT LOG::_ddsprintf ( PSZ pszOutString, PSZ pszFmtString, STACK_ADR Parm )
|
|---|
| 258 | /*
|
|---|
| 259 | ; ddsprintf - "sprintf" function on a vbl number of arguments.
|
|---|
| 260 | ;
|
|---|
| 261 | ; pszOutString - Output string saved here.
|
|---|
| 262 | ; pszFmtString - Input, Ascii string containing text and formating information.
|
|---|
| 263 | ; Parm - Input, Address of the 1st of the variable number of arguments.
|
|---|
| 264 | ;
|
|---|
| 265 | ;Returns:
|
|---|
| 266 | ; Length of string created.
|
|---|
| 267 | */
|
|---|
| 268 | {
|
|---|
| 269 | PSZ BuildPtr = pszOutString;
|
|---|
| 270 | PSZ pStr = (PSZ) pszFmtString;
|
|---|
| 271 | PSZ SubStr;
|
|---|
| 272 | WORD wBuildOption;
|
|---|
| 273 |
|
|---|
| 274 | while (*pStr) {
|
|---|
| 275 | // don't overflow target
|
|---|
| 276 | if (BuildPtr >= &pszOutString[ MAX_MsgLen-2 ] )
|
|---|
| 277 | break;
|
|---|
| 278 |
|
|---|
| 279 | switch (*pStr) { // the top switch
|
|---|
| 280 | case '%':
|
|---|
| 281 | wBuildOption=0;
|
|---|
| 282 | pStr++;
|
|---|
| 283 | if (*pStr=='0') {
|
|---|
| 284 | wBuildOption|=LEADING_ZEROES;
|
|---|
| 285 | pStr++;
|
|---|
| 286 | }
|
|---|
| 287 |
|
|---|
| 288 | switch(*pStr) { // switch on "%" options
|
|---|
| 289 | case 'x':
|
|---|
| 290 | case 'X':
|
|---|
| 291 | BuildPtr=_HexWordToASCII(BuildPtr, *Parm.WordPtr++,wBuildOption);
|
|---|
| 292 | pStr++;
|
|---|
| 293 | continue;
|
|---|
| 294 |
|
|---|
| 295 | case 'd':
|
|---|
| 296 | case 'D':
|
|---|
| 297 | BuildPtr=_DecWordToASCII(BuildPtr, *Parm.WordPtr++,wBuildOption);
|
|---|
| 298 | pStr++;
|
|---|
| 299 | continue;
|
|---|
| 300 |
|
|---|
| 301 | case 's':
|
|---|
| 302 | case 'S':
|
|---|
| 303 | SubStr = (PSZ) *Parm.StringPtr;
|
|---|
| 304 | while (*SubStr)
|
|---|
| 305 | *BuildPtr++ = *SubStr++;
|
|---|
| 306 | Parm.StringPtr++;
|
|---|
| 307 | BuildPtr--; // remove the \0
|
|---|
| 308 | pStr++;
|
|---|
| 309 | continue;
|
|---|
| 310 |
|
|---|
| 311 | case 'l':
|
|---|
| 312 | case 'L':
|
|---|
| 313 | pStr++;
|
|---|
| 314 | switch (*pStr) { // "%l" options
|
|---|
| 315 | case 'x':
|
|---|
| 316 | BuildPtr=_HexLongToASCII(BuildPtr, *Parm.LongPtr++,wBuildOption);
|
|---|
| 317 | pStr++;
|
|---|
| 318 | continue;
|
|---|
| 319 |
|
|---|
| 320 | case 'd':
|
|---|
| 321 | BuildPtr=_DecLongToASCII(BuildPtr, *Parm.LongPtr++,wBuildOption);
|
|---|
| 322 | pStr++;
|
|---|
| 323 | continue;
|
|---|
| 324 | } // end switch on "%l" options
|
|---|
| 325 | continue; // dunno what he wants
|
|---|
| 326 |
|
|---|
| 327 | case 0:
|
|---|
| 328 | continue;
|
|---|
| 329 | } // end switch on "%" options
|
|---|
| 330 | break;
|
|---|
| 331 |
|
|---|
| 332 | case '\\':
|
|---|
| 333 | pStr++;
|
|---|
| 334 | switch (*pStr) {
|
|---|
| 335 | case 'n':
|
|---|
| 336 | *BuildPtr++=CR;
|
|---|
| 337 | *BuildPtr++=LF;
|
|---|
| 338 | pStr++;
|
|---|
| 339 | continue;
|
|---|
| 340 |
|
|---|
| 341 | case 'r':
|
|---|
| 342 | *BuildPtr++=CR;
|
|---|
| 343 | pStr++;
|
|---|
| 344 | continue;
|
|---|
| 345 |
|
|---|
| 346 | case 0:
|
|---|
| 347 | continue;
|
|---|
| 348 |
|
|---|
| 349 | } // end switch
|
|---|
| 350 |
|
|---|
| 351 | break; // case '\\'
|
|---|
| 352 |
|
|---|
| 353 | case '\n':
|
|---|
| 354 | pStr++;
|
|---|
| 355 | *BuildPtr++=CR;
|
|---|
| 356 | *BuildPtr++=LF;
|
|---|
| 357 | continue;
|
|---|
| 358 | break;
|
|---|
| 359 | } // end top switch
|
|---|
| 360 |
|
|---|
| 361 | *BuildPtr++=*pStr++;
|
|---|
| 362 | } // end while
|
|---|
| 363 |
|
|---|
| 364 | *BuildPtr=0; // cauterize the string
|
|---|
| 365 | return strlen( (char *) pszOutString );
|
|---|
| 366 | }
|
|---|
| 367 |
|
|---|
| 368 | USHORT _CheckRing(void);
|
|---|
| 369 | #pragma aux _CheckRing = \
|
|---|
| 370 | "push cs" \
|
|---|
| 371 | "pop ax " \
|
|---|
| 372 | "and ax,0003H" \
|
|---|
| 373 | parm nomemory \
|
|---|
| 374 | modify [ax];
|
|---|
| 375 |
|
|---|
| 376 | //----------------------- ddputstring -
|
|---|
| 377 | void LOG::_ddputstring ( USHORT iMsgNum, PSZ pszMsg )
|
|---|
| 378 | {
|
|---|
| 379 | int iMsgLength = strlen( (char *) pszMsg );
|
|---|
| 380 | // Sring length of the message.
|
|---|
| 381 |
|
|---|
| 382 | // Need to know whether we're still executing at Ring 3.
|
|---|
| 383 | if ( _bInRing3 )
|
|---|
| 384 | if (_CheckRing() != 3) // In Ring 3 last time, still there now?
|
|---|
| 385 | _bInRing3 = FALSE; // Nope, and no need to check again.
|
|---|
| 386 |
|
|---|
| 387 | // --- Index through possible places to save this message.
|
|---|
| 388 | for (int destination=0; destination != _nMsgSinks; ++destination) {
|
|---|
| 389 | if ( bMsgSink[destination] ) {
|
|---|
| 390 | switch (destination) {
|
|---|
| 391 | case _Display:
|
|---|
| 392 | // Put message on the display only if we're in Ring 3.
|
|---|
| 393 | if ( _bInRing3 ) {
|
|---|
| 394 | static CHAR szCRLF[] = "\r\n";
|
|---|
| 395 | static int iCRLF_Len = strlen( (char *) szCRLF );
|
|---|
| 396 | DosPutMessage( 1, iMsgLength, (PCHAR) pszMsg );
|
|---|
| 397 | DosPutMessage( 1, iCRLF_Len, (PCHAR) szCRLF );
|
|---|
| 398 | }
|
|---|
| 399 | break;
|
|---|
| 400 | case _SerialLine:
|
|---|
| 401 | { PCHAR pChar = (PCHAR) pszMsg;
|
|---|
| 402 | while (*pChar)
|
|---|
| 403 | _CharOut(*pChar++);
|
|---|
| 404 | }
|
|---|
| 405 | _CharOut( '\n' );
|
|---|
| 406 | break;
|
|---|
| 407 | case _ErrorLog:
|
|---|
| 408 | if ( _bInRing3 )
|
|---|
| 409 | DosSysTrace( _DosTraceMajorCode, iMsgLength, iMsgNum, (PCHAR) pszMsg);
|
|---|
| 410 | else
|
|---|
| 411 | DevHelp_RAS( _DosTraceMajorCode, iMsgNum, iMsgLength, pszMsg);
|
|---|
| 412 | break;
|
|---|
| 413 | case _TraceLog:
|
|---|
| 414 | if ( _bInRing3 )
|
|---|
| 415 | DosSysTrace( _DosTraceMajorCode, iMsgLength, iMsgNum, (PCHAR) pszMsg);
|
|---|
| 416 | else
|
|---|
| 417 | DevHelp_RAS( _DosTraceMajorCode, iMsgNum, iMsgLength, pszMsg);
|
|---|
| 418 | break;
|
|---|
| 419 | }
|
|---|
| 420 | }
|
|---|
| 421 | }
|
|---|
| 422 | }
|
|---|
| 423 |
|
|---|
| 424 |
|
|---|
| 425 | void LOG::_CharOut(char c)
|
|---|
| 426 | /* Sends a single character to the COM: port. */
|
|---|
| 427 | {
|
|---|
| 428 | UCHAR inbyte;
|
|---|
| 429 |
|
|---|
| 430 | inbyte = inp((_ComPort + UART_LINE_STAT));
|
|---|
| 431 | while ((inbyte & 0x20) != 0x20) {
|
|---|
| 432 | iodelay(1);
|
|---|
| 433 | inbyte = inp((_ComPort + UART_LINE_STAT));
|
|---|
| 434 | }
|
|---|
| 435 | // Send the character
|
|---|
| 436 | outp((_ComPort + UART_DATA), c);
|
|---|
| 437 | }
|
|---|
| 438 |
|
|---|
| 439 |
|
|---|
| 440 | // Create a log. The parms indicate where to stream the messages to.
|
|---|
| 441 | LOG::LOG( USHORT DosTraceMajorCode, PSZ* apszMsgText ) :
|
|---|
| 442 | _DosTraceMajorCode ( DosTraceMajorCode ),
|
|---|
| 443 | _bInRing3 ( _CheckRing() != 0 ),
|
|---|
| 444 | _apszMsgText ( apszMsgText ),
|
|---|
| 445 | _ComPort ( 0x2F8 )
|
|---|
| 446 | {
|
|---|
| 447 | bMsgSink[ _Display ] = FALSE;
|
|---|
| 448 | bMsgSink[ _SerialLine ] = FALSE;
|
|---|
| 449 | bMsgSink[ _ErrorLog ] = FALSE;
|
|---|
| 450 | bMsgSink[ _TraceLog ] = TRUE;
|
|---|
| 451 | }
|
|---|
| 452 |
|
|---|
| 453 |
|
|---|
| [553] | 454 | void LOG::vTrace( USHORT eventNum )
|
|---|
| [354] | 455 | /* Log the specified event. */
|
|---|
| 456 | {
|
|---|
| 457 | //--- Output the string.
|
|---|
| 458 | _ddputstring( eventNum, _apszMsgText[ eventNum ] );
|
|---|
| 459 | }
|
|---|
| 460 |
|
|---|
| 461 |
|
|---|
| [553] | 462 | void LOG::vLog( USHORT eventNum, ... )
|
|---|
| [354] | 463 | /* Log the specified event, with data. */
|
|---|
| 464 | {
|
|---|
| 465 | STACK_ADR Arg1Adr; // Points to the 1st of a variable number
|
|---|
| 466 | // of arguments in the stack.
|
|---|
| 467 | PUSHORT pEventNum;
|
|---|
| 468 |
|
|---|
| 469 | //--- Get the stack address of the 1st argument following the error number.
|
|---|
| 470 | pEventNum = (PUSHORT) &eventNum; // Adr of event num
|
|---|
| 471 | ++pEventNum; // Advance ptr past 1st arg.
|
|---|
| 472 | Arg1Adr.VoidPtr = (PVOID) pEventNum; // Adr of 1st after err num.
|
|---|
| 473 |
|
|---|
| 474 | //--- Format the message and any of the data.
|
|---|
| 475 | //### Should have check here for error number out of range.
|
|---|
| 476 | _ddsprintf( _dd_BuildString, _apszMsgText[ eventNum ], Arg1Adr );
|
|---|
| 477 |
|
|---|
| 478 | //--- Output the string.
|
|---|
| 479 | _ddputstring( eventNum, _dd_BuildString );
|
|---|
| 480 | }
|
|---|
| 481 |
|
|---|
| 482 |
|
|---|
| 483 | PERFLOG::PERFLOG( USHORT DosTraceMajorCode, PSZ* apszMsgText ) :
|
|---|
| 484 | LOG( DosTraceMajorCode, apszMsgText )
|
|---|
| 485 | {
|
|---|
| 486 | bMsgSink[ _Display ] = FALSE;
|
|---|
| 487 | bMsgSink[ _SerialLine ] = FALSE;
|
|---|
| 488 | bMsgSink[ _ErrorLog ] = FALSE;
|
|---|
| 489 | bMsgSink[ _TraceLog ] = TRUE;
|
|---|
| 490 | }
|
|---|
| 491 |
|
|---|
| [553] | 492 | void PERFLOG::vTrace( USHORT eventNum )
|
|---|
| [354] | 493 | {
|
|---|
| 494 | RDTSC_COUNT rdtsc_result; // Output from Pentium timing instruction.
|
|---|
| 495 | rdtsc( &rdtsc_result );
|
|---|
| 496 | if ( _CheckRing() )
|
|---|
| 497 | DosSysTrace( _DosTraceMajorCode, sizeof(RDTSC_COUNT), eventNum, (PCHAR) &rdtsc_result);
|
|---|
| 498 | else
|
|---|
| 499 | DevHelp_RAS( _DosTraceMajorCode, eventNum, sizeof(RDTSC_COUNT), (PSZ) &rdtsc_result);
|
|---|
| 500 | }
|
|---|
| 501 |
|
|---|
| 502 |
|
|---|
| 503 | USHORT BINARYLOG::_ddsprintf ( PSZ pszOutString, PSZ pszFmtString, STACK_ADR Parm )
|
|---|
| 504 | /*
|
|---|
| 505 | ; ddsprintf - "sprintf" function on a vbl number of arguments.
|
|---|
| 506 | ;
|
|---|
| 507 | ; pszOutString - Output string saved here.
|
|---|
| 508 | ; pszFmtString - Input, Ascii string containing text and formating information.
|
|---|
| 509 | ; Parm - Input, Address of the 1st of the variable number of arguments.
|
|---|
| 510 | ;
|
|---|
| 511 | ;Returns
|
|---|
| 512 | ; USHORT nDataLen - lentgh of the data string that is saved in pszOutString
|
|---|
| 513 | ;
|
|---|
| 514 | ;Notes
|
|---|
| 515 | ; This function needed to reverse the order of the args pushed on the stack.
|
|---|
| 516 | */
|
|---|
| 517 | {
|
|---|
| 518 | PSZ pStr = (PSZ) pszFmtString;
|
|---|
| 519 | USHORT uStrLen = 0; // Total string length accumulated here.
|
|---|
| 520 | USHORT nBytes; // Length of one data item saved here.
|
|---|
| 521 | BOOL lFlag;
|
|---|
| 522 |
|
|---|
| 523 | /*--- Find out how many bytes of log data have been pushed on
|
|---|
| 524 | * the stack. Do this by walking formatting string and counting
|
|---|
| 525 | * the number of bytes expected by the format control characters.
|
|---|
| 526 | */
|
|---|
| 527 | while ( *pStr ) {
|
|---|
| 528 |
|
|---|
| 529 | /* ### FUTURE: Want to seek forward to '%' or '0'. Any quick way to do it? */
|
|---|
| 530 |
|
|---|
| 531 | if (*pStr != '%') { // If not the start of a format directive,
|
|---|
| 532 | ++pStr; // then continue to next byte.
|
|---|
| 533 | continue;
|
|---|
| 534 | }
|
|---|
| 535 |
|
|---|
| 536 | nBytes = 0; // Not 0 indicates a recognized sequence.
|
|---|
| 537 | lFlag = FALSE; // Set TRUE when "L" is present.
|
|---|
| 538 | ++ pStr; // Advance past '%'
|
|---|
| 539 | if (*pStr == '0') // Advance past '0'
|
|---|
| 540 | ++pStr;
|
|---|
| 541 | if (*pStr == 'l' || *pStr == 'L') {
|
|---|
| 542 | ++pStr; // Advance past "L" if present.
|
|---|
| 543 | lFlag = TRUE;
|
|---|
| 544 | }
|
|---|
| 545 |
|
|---|
| 546 | if (*pStr == 'b' || *pStr == 'B')
|
|---|
| 547 | nBytes = 1;
|
|---|
| 548 | else if (*pStr == 'd' || *pStr == 'D' || *pStr == 'x' || *pStr == 'X') {
|
|---|
| 549 | if (lFlag)
|
|---|
| 550 | nBytes = 4;
|
|---|
| 551 | else
|
|---|
| 552 | nBytes = 2;
|
|---|
| 553 | }
|
|---|
| 554 | else if (*pStr == 'q' || *pStr == 'Q')
|
|---|
| 555 | nBytes = 8;
|
|---|
| 556 |
|
|---|
| 557 | /* If we recognize the formatting command, then count the bytes,
|
|---|
| 558 | * otherwise ignore this '%' directive and continue.
|
|---|
| 559 | */
|
|---|
| 560 | if (nBytes) {
|
|---|
| 561 | _fmemcpy( (PVOID) pszOutString, Parm.VoidPtr, nBytes );
|
|---|
| 562 | //Rudi: stack is word-wise !
|
|---|
| 563 | if( nBytes == 1 )
|
|---|
| 564 | Parm.BytePtr += 2;
|
|---|
| 565 | else
|
|---|
| 566 | Parm.BytePtr += nBytes;
|
|---|
| 567 |
|
|---|
| 568 | pszOutString += nBytes;
|
|---|
| 569 | uStrLen += nBytes;
|
|---|
| 570 | }
|
|---|
| 571 |
|
|---|
| 572 | ++pStr;
|
|---|
| 573 | }
|
|---|
| 574 | return( uStrLen );
|
|---|
| 575 | }
|
|---|
| 576 |
|
|---|
| 577 |
|
|---|
| 578 | BINARYLOG::BINARYLOG( USHORT DosTraceMajorCode, PSZ* apszMsgText ) :
|
|---|
| 579 | LOG( DosTraceMajorCode, apszMsgText )
|
|---|
| 580 | {
|
|---|
| 581 | bMsgSink[ _Display ] = FALSE;
|
|---|
| 582 | bMsgSink[ _SerialLine ] = FALSE;
|
|---|
| 583 | bMsgSink[ _ErrorLog ] = FALSE;
|
|---|
| 584 | bMsgSink[ _TraceLog ] = TRUE;
|
|---|
| 585 | }
|
|---|
| 586 |
|
|---|
| 587 |
|
|---|
| [553] | 588 | void BINARYLOG::vTrace( USHORT eventNum )
|
|---|
| [354] | 589 | /* Log the specified trace point. */
|
|---|
| 590 | {
|
|---|
| 591 | //--- Save the event in the system trace log.
|
|---|
| 592 | if ( _CheckRing() )
|
|---|
| 593 | DosSysTrace( _DosTraceMajorCode, 0, eventNum, (PCHAR) NULL );
|
|---|
| 594 | else
|
|---|
| 595 | DevHelp_RAS( _DosTraceMajorCode, eventNum, 0, (PSZ) NULL );
|
|---|
| 596 | }
|
|---|
| 597 |
|
|---|
| 598 |
|
|---|
| 599 | void BINARYLOG::vLog( USHORT eventNum, ... )
|
|---|
| 600 | /* Log the specified trace point, with data. */
|
|---|
| 601 | {
|
|---|
| 602 | STACK_ADR pStack; // Points to the 1st of a variable number
|
|---|
| 603 | // of arguments in the stack.
|
|---|
| 604 | USHORT usLength; // Number of bytes to log.
|
|---|
| 605 |
|
|---|
| 606 | //--- Get the stack address of the 1st argument following the event number.
|
|---|
| 607 | pStack.WordPtr = (WORD*) &eventNum; // Adr of event num
|
|---|
| 608 | ++pStack.WordPtr; // Advance ptr to 1st arg after event number.
|
|---|
| 609 |
|
|---|
| 610 | //--- Invoke binary version of _ddsprintf() to get args into the right order.
|
|---|
| 611 | usLength = _ddsprintf( _dd_BuildString, _apszMsgText[ eventNum ], pStack );
|
|---|
| 612 |
|
|---|
| 613 | //--- Save data bytes in the System trace log and return.
|
|---|
| 614 | if ( _CheckRing() )
|
|---|
| 615 | DosSysTrace( _DosTraceMajorCode, usLength, eventNum, (PCHAR) _dd_BuildString );
|
|---|
| 616 | else
|
|---|
| 617 | DevHelp_RAS( _DosTraceMajorCode, eventNum, usLength, (PSZ) _dd_BuildString );
|
|---|
| 618 | }
|
|---|