|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1993 Microsoft Corporation ! 4: Copyright (c) 1993 Logitech Inc. ! 5: ! 6: Module Name: ! 7: ! 8: uart.c ! 9: ! 10: Abstract: ! 11: ! 12: Environment: ! 13: ! 14: Kernel mode only. ! 15: ! 16: Notes: ! 17: ! 18: Revision History: ! 19: ! 20: --*/ ! 21: ! 22: #include "ntddk.h" ! 23: #include "uart.h" ! 24: #include "sermouse.h" ! 25: #include "debug.h" ! 26: ! 27: #ifdef ALLOC_PRAGMA ! 28: #pragma alloc_text(init,UARTSetFifo) ! 29: #pragma alloc_text(init,UARTGetInterruptCtrl) ! 30: #pragma alloc_text(init,UARTSetInterruptCtrl) ! 31: #pragma alloc_text(init,UARTGetLineCtrl) ! 32: #pragma alloc_text(init,UARTSetLineCtrl) ! 33: #pragma alloc_text(init,UARTGetModemCtrl) ! 34: #pragma alloc_text(init,UARTSetModemCtrl) ! 35: #pragma alloc_text(init,UARTSetDlab) ! 36: #pragma alloc_text(init,UARTGetBaudRate) ! 37: #pragma alloc_text(init,UARTSetBaudRate) ! 38: #pragma alloc_text(init,UARTGetState) ! 39: #pragma alloc_text(init,UARTSetState) ! 40: #pragma alloc_text(init,UARTReadChar) ! 41: #pragma alloc_text(init,UARTIsTransmitEmpty) ! 42: #pragma alloc_text(init,UARTWriteChar) ! 43: #pragma alloc_text(init,UARTWriteString) ! 44: #endif // ALLOC_PRAGMA ! 45: ! 46: // ! 47: // Constants ! 48: // ! 49: ! 50: ! 51: VOID ! 52: UARTSetFifo( ! 53: PUCHAR Port, ! 54: UCHAR Value ! 55: ) ! 56: /*++ ! 57: ! 58: Routine Description: ! 59: ! 60: Set the FIFO register. ! 61: ! 62: Arguments: ! 63: ! 64: Port - Pointer to the serial port. ! 65: ! 66: Value - The FIFO control mask. ! 67: ! 68: Return Value: ! 69: ! 70: None. ! 71: ! 72: --*/ ! 73: { ! 74: WRITE_PORT_UCHAR(Port + ACE_IIDR, Value); ! 75: } ! 76: UCHAR ! 77: UARTGetInterruptCtrl( ! 78: PUCHAR Port ! 79: ) ! 80: /*++ ! 81: ! 82: Routine Description: ! 83: ! 84: Get the serial port interrupt control register. ! 85: ! 86: Arguments: ! 87: ! 88: Port - Pointer to the serial port. ! 89: ! 90: Return Value: ! 91: ! 92: Serial port interrupt control register value. ! 93: ! 94: --*/ ! 95: { ! 96: return READ_PORT_UCHAR(Port + ACE_IER); ! 97: } ! 98: ! 99: UCHAR ! 100: UARTSetInterruptCtrl( ! 101: PUCHAR Port, ! 102: UCHAR Value ! 103: ) ! 104: /*++ ! 105: ! 106: Routine Description: ! 107: ! 108: Set the interrupt control register. ! 109: ! 110: Arguments: ! 111: ! 112: Port - Pointer to the serial port. ! 113: ! 114: Value - The interrupt control mask. ! 115: ! 116: Return Value: ! 117: ! 118: Previous interrupt control value. ! 119: ! 120: --*/ ! 121: { ! 122: UCHAR oldValue = UARTGetInterruptCtrl(Port); ! 123: WRITE_PORT_UCHAR(Port + ACE_IER, Value); ! 124: ! 125: return oldValue; ! 126: } ! 127: ! 128: ! 129: UCHAR ! 130: UARTGetLineCtrl( ! 131: PUCHAR Port ! 132: ) ! 133: /*++ ! 134: ! 135: Routine Description: ! 136: ! 137: Get the serial port line control register. ! 138: ! 139: Arguments: ! 140: ! 141: Port - Pointer to the serial port. ! 142: ! 143: Return Value: ! 144: ! 145: Serial port line control value. ! 146: ! 147: --*/ ! 148: { ! 149: return READ_PORT_UCHAR(Port + ACE_LCR); ! 150: } ! 151: ! 152: UCHAR ! 153: UARTSetLineCtrl( ! 154: PUCHAR Port, ! 155: UCHAR Value ! 156: ) ! 157: /*++ ! 158: ! 159: Routine Description: ! 160: ! 161: Set the serial port line control register. ! 162: ! 163: Arguments: ! 164: ! 165: Port - Pointer to the serial port. ! 166: ! 167: Value - New line control value. ! 168: ! 169: Return Value: ! 170: ! 171: Previous serial line control register value. ! 172: ! 173: --*/ ! 174: { ! 175: UCHAR oldValue = UARTGetLineCtrl(Port); ! 176: WRITE_PORT_UCHAR(Port + ACE_LCR, Value); ! 177: ! 178: return oldValue; ! 179: } ! 180: ! 181: ! 182: UCHAR ! 183: UARTGetModemCtrl( ! 184: PUCHAR Port ! 185: ) ! 186: /*++ ! 187: ! 188: Routine Description: ! 189: ! 190: Get the serial port modem control register. ! 191: ! 192: Arguments: ! 193: ! 194: Port - Pointer to the serial port. ! 195: ! 196: Return Value: ! 197: ! 198: Serial port modem control register value. ! 199: ! 200: --*/ ! 201: { ! 202: return READ_PORT_UCHAR(Port + ACE_MCR); ! 203: } ! 204: ! 205: UCHAR ! 206: UARTSetModemCtrl( ! 207: PUCHAR Port, ! 208: UCHAR Value ! 209: ) ! 210: /*++ ! 211: ! 212: Routine Description: ! 213: ! 214: Set the serial port modem control register. ! 215: ! 216: Arguments: ! 217: ! 218: Port - Pointer to the serial port. ! 219: ! 220: Return Value: ! 221: ! 222: Previous modem control register value. ! 223: ! 224: --*/ ! 225: { ! 226: ! 227: UCHAR oldValue = UARTGetModemCtrl(Port); ! 228: WRITE_PORT_UCHAR(Port + ACE_MCR, Value); ! 229: ! 230: return oldValue; ! 231: } ! 232: ! 233: ! 234: BOOLEAN ! 235: UARTSetDlab( ! 236: PUCHAR Port, ! 237: BOOLEAN Set ! 238: ) ! 239: /*++ ! 240: ! 241: Routine Description: ! 242: ! 243: Set/reset the baud rate access bit. ! 244: ! 245: Arguments: ! 246: ! 247: Port - Pointer to the serial port. ! 248: ! 249: Set - Set or Reset (TRUE/FALSE) the baud rate access bit. ! 250: ! 251: Return Value: ! 252: ! 253: The previous baud rate access bit setting. ! 254: ! 255: --*/ ! 256: { ! 257: UCHAR lineControl = UARTGetLineCtrl(Port); ! 258: UCHAR newLineControl = Set ? lineControl | ACE_DLAB : ! 259: lineControl & ~ACE_DLAB; ! 260: ! 261: WRITE_PORT_UCHAR(Port + ACE_LCR, newLineControl); ! 262: ! 263: return lineControl & ACE_DLAB; ! 264: } ! 265: ! 266: ULONG ! 267: UARTGetBaudRate( ! 268: PUCHAR Port, ! 269: ULONG BaudClock ! 270: ) ! 271: /*++ ! 272: ! 273: Routine Description: ! 274: ! 275: Get the serial port baud rate setting. ! 276: ! 277: Arguments: ! 278: ! 279: Port - Pointer to the serial port. ! 280: ! 281: BaudClock - The external frequency driving the serial chip. ! 282: ! 283: Return Value: ! 284: ! 285: Serial port baud rate. ! 286: ! 287: --*/ ! 288: { ! 289: USHORT baudRateDivisor; ! 290: ULONG baudRateFactor = BaudClock/BAUD_GENERATOR_DIVISOR; ! 291: ! 292: // ! 293: // Set the baud rate access bit. ! 294: // ! 295: ! 296: UARTSetDlab(Port, TRUE); ! 297: ! 298: // ! 299: // Read the baud rate factor. ! 300: // ! 301: ! 302: baudRateDivisor = READ_PORT_UCHAR(Port + ACE_DLL); ! 303: baudRateDivisor |= READ_PORT_UCHAR(Port + ACE_DLM) << 8; ! 304: ! 305: // ! 306: // Reset the baud rate bit for normal data access. ! 307: // ! 308: ! 309: UARTSetDlab(Port, FALSE); ! 310: ! 311: // ! 312: // Make sure the divisor is not zero. ! 313: // ! 314: ! 315: if (baudRateDivisor == 0) { ! 316: baudRateDivisor = 1; ! 317: } ! 318: ! 319: return baudRateFactor / baudRateDivisor; ! 320: } ! 321: ! 322: VOID ! 323: UARTSetBaudRate( ! 324: PUCHAR Port, ! 325: ULONG BaudRate, ! 326: ULONG BaudClock ! 327: ) ! 328: /*++ ! 329: ! 330: Routine Description: ! 331: ! 332: Set the serial port baud rate. ! 333: ! 334: Arguments: ! 335: ! 336: Port - Pointer to the serial port. ! 337: ! 338: BaudRate - New serial port baud rate. ! 339: ! 340: BaudClock - The external frequency driving the serial chip. ! 341: ! 342: Return Value: ! 343: ! 344: None. ! 345: ! 346: --*/ ! 347: { ! 348: ! 349: ULONG baudRateFactor = BaudClock/BAUD_GENERATOR_DIVISOR; ! 350: USHORT baudRateDivisor; ! 351: ! 352: SerMouPrint((2, "SERMOUSE-SetBaudRate: Enter\n")); ! 353: ! 354: baudRateDivisor = baudRateFactor / BaudRate; ! 355: UARTSetDlab(Port, TRUE); ! 356: WRITE_PORT_UCHAR(Port + ACE_DLL, (UCHAR)baudRateDivisor); ! 357: WRITE_PORT_UCHAR(Port + ACE_DLM, (UCHAR)(baudRateDivisor >> 8)); ! 358: UARTSetDlab(Port, FALSE); ! 359: SerMouPrint((2, "SERMOUSE-New BaudRate: %u\n", BaudRate)); ! 360: ! 361: SerMouPrint((2, "SERMOUSE-SetBaudRate: Exit\n")); ! 362: ! 363: return; ! 364: } ! 365: ! 366: ! 367: VOID ! 368: UARTGetState( ! 369: PUCHAR Port, ! 370: PUART Uart, ! 371: ULONG BaudClock ! 372: ) ! 373: /*++ ! 374: ! 375: Routine Description: ! 376: ! 377: Get the complete state of the serial port. May be used for save/restore. ! 378: ! 379: Arguments: ! 380: ! 381: Port - Pointer to the serial port. ! 382: ! 383: Uart - Pointer to a serial port structure. ! 384: ! 385: BaudClock - The external frequency driving the serial chip. ! 386: ! 387: Return Value: ! 388: ! 389: None. ! 390: ! 391: --*/ ! 392: { ! 393: Uart->LineCtrl = UARTGetLineCtrl(Port); ! 394: Uart->ModemCtrl = UARTGetModemCtrl(Port); ! 395: Uart->InterruptCtrl = UARTGetInterruptCtrl(Port); ! 396: Uart->BaudRate = UARTGetBaudRate(Port, BaudClock); ! 397: ! 398: return; ! 399: } ! 400: ! 401: VOID ! 402: UARTSetState( ! 403: PUCHAR Port, ! 404: PUART Uart, ! 405: ULONG BaudClock ! 406: ) ! 407: /*++ ! 408: ! 409: Routine Description: ! 410: ! 411: Set the complete state of a serial port. ! 412: ! 413: Arguments: ! 414: ! 415: Port - Pointer to the serial port. ! 416: ! 417: Uart - Pointer to a serial port structure. ! 418: ! 419: BaudClock - The external frequency driving the serial chip. ! 420: ! 421: Return Value: ! 422: ! 423: None. ! 424: ! 425: --*/ ! 426: { ! 427: UARTSetLineCtrl(Port, Uart->LineCtrl); ! 428: UARTSetModemCtrl(Port, Uart->ModemCtrl); ! 429: UARTSetInterruptCtrl(Port, Uart->InterruptCtrl); ! 430: UARTSetBaudRate(Port, Uart->BaudRate, BaudClock); ! 431: ! 432: return; ! 433: } ! 434: ! 435: ! 436: BOOLEAN ! 437: UARTIsReceiveBufferFull( ! 438: PUCHAR Port ! 439: ) ! 440: /*++ ! 441: ! 442: Routine Description: ! 443: ! 444: Check whether the serial port input buffer is full. ! 445: ! 446: Arguments: ! 447: ! 448: Port - Pointer to the serial port. ! 449: ! 450: Return Value: ! 451: ! 452: TRUE if a character is present in the input buffer, otherwise FALSE. ! 453: ! 454: --*/ ! 455: { ! 456: return READ_PORT_UCHAR(Port + ACE_LSR) & ACE_DR; ! 457: } ! 458: ! 459: ! 460: BOOLEAN ! 461: UARTReadCharNoWait( ! 462: PUCHAR Port, ! 463: PUCHAR Value ! 464: ) ! 465: /*++ ! 466: ! 467: Routine Description: ! 468: ! 469: Read a character from the serial port and return immediately. ! 470: ! 471: Arguments: ! 472: ! 473: Port - Pointer to the serial port. ! 474: ! 475: Value - The character read from the serial port input buffer. ! 476: ! 477: Return Value: ! 478: ! 479: TRUE if character has been read, FALSE otherwise. ! 480: ! 481: --*/ ! 482: { ! 483: BOOLEAN charReady = FALSE; ! 484: ! 485: if ( UARTIsReceiveBufferFull(Port) ) { ! 486: *Value = READ_PORT_UCHAR(Port + ACE_RBR); ! 487: charReady = TRUE; ! 488: } ! 489: ! 490: return charReady; ! 491: } ! 492: ! 493: BOOLEAN ! 494: UARTReadChar( ! 495: PUCHAR Port, ! 496: PUCHAR Value, ! 497: ULONG Timeout ! 498: ) ! 499: /*++ ! 500: ! 501: Routine Description: ! 502: ! 503: Read a character from the serial port. Waits until a character has ! 504: been read or the timeout value is reached. ! 505: ! 506: Arguments: ! 507: ! 508: Port - Pointer to the serial port. ! 509: ! 510: Value - The character read from the serial port input buffer. ! 511: ! 512: Timeout - The timeout value in milliseconds for the read. ! 513: ! 514: Return Value: ! 515: ! 516: TRUE if a character has been read, FALSE if a timeout occured. ! 517: ! 518: --*/ ! 519: { ! 520: ! 521: ULONG i, j; ! 522: BOOLEAN returnValue = FALSE; ! 523: ! 524: ! 525: // ! 526: // Exit when a character is found or the timeout value is reached. ! 527: // ! 528: ! 529: for (i = 0; i < Timeout; i++) { ! 530: for (j = 0; j < MS_TO_MICROSECONDS; j++) { ! 531: if ((returnValue = UARTReadCharNoWait(Port, Value)) == TRUE) { ! 532: ! 533: // ! 534: // Got a character. ! 535: // ! 536: ! 537: break; ! 538: } else { ! 539: ! 540: // ! 541: // Stall 1 microsecond and then try to read again. ! 542: // ! 543: ! 544: KeStallExecutionProcessor(1); ! 545: } ! 546: } ! 547: if (returnValue) { ! 548: break; ! 549: } ! 550: } ! 551: ! 552: return(returnValue); ! 553: } ! 554: ! 555: BOOLEAN ! 556: UARTFlushReadBuffer( ! 557: PUCHAR Port ! 558: ) ! 559: /*++ ! 560: ! 561: Routine Description: ! 562: ! 563: Flush the serial port input buffer. ! 564: ! 565: Arguments: ! 566: ! 567: Port - Pointer to the serial port. ! 568: ! 569: Return Value: ! 570: ! 571: TRUE. ! 572: ! 573: --*/ ! 574: { ! 575: UCHAR value; ! 576: ! 577: SerMouPrint((4, "SERMOUSE-UARTFlushReadBuffer: Enter\n")); ! 578: while (UARTReadCharNoWait(Port, &value)) { ! 579: /* Nothing */ ! 580: } ! 581: SerMouPrint((4, "SERMOUSE-UARTFlushReadBuffer: Exit\n")); ! 582: ! 583: return TRUE; ! 584: } ! 585: ! 586: ! 587: BOOLEAN ! 588: UARTIsTransmitEmpty( ! 589: PUCHAR Port ! 590: ) ! 591: /*++ ! 592: ! 593: Routine Description: ! 594: ! 595: Check whether the serial port transmit buffer is empty. ! 596: ! 597: Note: We also check whether the shift register is empty. This is ! 598: not critical in our case, but allows some more delay between characters ! 599: sent to a device. (Safe, safe...) ! 600: ! 601: Arguments: ! 602: ! 603: Port - Pointer to the serial port. ! 604: ! 605: Return Value: ! 606: ! 607: TRUE if the serial port transmit buffer is empty. ! 608: ! 609: --*/ ! 610: { ! 611: return ((READ_PORT_UCHAR((PUCHAR) (Port + ACE_LSR)) & ! 612: (ACE_TSRE | ACE_THRE)) == (ACE_THRE | ACE_TSRE)); ! 613: } ! 614: ! 615: ! 616: BOOLEAN ! 617: UARTWriteChar( ! 618: PUCHAR Port, ! 619: UCHAR Value ! 620: ) ! 621: /*++ ! 622: ! 623: Routine Description: ! 624: ! 625: Write a character to a serial port. Make sure the transmit buffer ! 626: is empty before we write there. ! 627: ! 628: Arguments: ! 629: ! 630: Port - Pointer to the serial port. ! 631: ! 632: Value - Value to write to the serial port. ! 633: ! 634: Return Value: ! 635: ! 636: TRUE. ! 637: ! 638: --*/ ! 639: { ! 640: while (!UARTIsTransmitEmpty(Port)) { ! 641: /* Nothing */ ! 642: } ! 643: WRITE_PORT_UCHAR(Port + ACE_THR, Value); ! 644: ! 645: return TRUE; ! 646: } ! 647: ! 648: BOOLEAN ! 649: UARTWriteString( ! 650: PUCHAR Port, ! 651: PSZ Buffer ! 652: ) ! 653: /*++ ! 654: ! 655: Routine Description: ! 656: ! 657: Write a zero-terminated string to the serial port. ! 658: ! 659: Arguments: ! 660: ! 661: Port - Pointer to the serial port. ! 662: ! 663: Buffer - Pointer to a zero terminated string to write to ! 664: the serial port. ! 665: ! 666: Return Value: ! 667: ! 668: TRUE. ! 669: ! 670: --*/ ! 671: { ! 672: PSZ current = Buffer; ! 673: ! 674: while (*current) { ! 675: UARTWriteChar(Port, *current++); ! 676: } ! 677: ! 678: return TRUE; ! 679: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.