|
|
1.1 ! root 1: /* ! 2: * PC_com.c ! 3: * ! 4: * This module handles the virtual UART I/O and interrupt interface ! 5: * ! 6: * Note: ! 7: * Refer to National Semiconductor literature for a detailed description ! 8: * of the NS16450/NS8250A UART. Refer to the PC-XT Tech Ref Manual ! 9: * Section 1-185 for a description of the Asynchronous Adaptor Card. ! 10: * ! 11: * copyright 1992 by Microsoft Corporation ! 12: * portions copyright 1991 by Insignia Solutions Ltd., used by permission. ! 13: * ! 14: * revision history: ! 15: * 24-Dec-1992 John Morgan: written based (in part) on ! 16: * serial driver support from Windows NT VDM. ! 17: * ! 18: */ ! 19: ! 20: ! 21: // ! 22: // useful utility macros ! 23: // ! 24: #include "util_def.h" ! 25: ! 26: // ! 27: // standard library include files ! 28: // ! 29: #include <windows.h> ! 30: ! 31: #include <stdio.h> ! 32: #include <ctype.h> ! 33: #include <sys/types.h> ! 34: #include <string.h> ! 35: ! 36: // ! 37: // COM_VDD specific include files ! 38: // ! 39: #include "com_vdd.h" ! 40: #include "PC_def.h" ! 41: #include "PC_com.h" ! 42: #include "NT_com.h" ! 43: #include "vddsvc.h" ! 44: ! 45: /* ! 46: * ===================================================================== ! 47: * Subsidiary functions - for interrupt emulation ! 48: * ===================================================================== ! 49: */ ! 50: static void check_interrupt( UART_STATE *asp ) ! 51: { ! 52: /* ! 53: * Follow somewhat dubious advice on Page 1-188 of XT Tech Ref ! 54: * regarding the adapter card sending interrupts to the system. ! 55: * Apparently confirmed by the logic diagram. ! 56: */ ! 57: if (asp->out2_state ! 58: && !asp->loopback_state ! 59: && (asp->data_available_interrupt_state ! 60: || asp->tx_holding_register_empty_interrupt_state ! 61: || asp->receiver_line_status_interrupt_state ! 62: || asp->modem_status_interrupt_state)) ! 63: { ! 64: if (!asp->interrupt_line_state) ! 65: { ! 66: asp->interrupt_line_state = TRUE; ! 67: VDDSimulateInterrupt( 0, asp->hw_interrupt_priority, 1); ! 68: } ! 69: } ! 70: else ! 71: { ! 72: asp->interrupt_line_state = FALSE; ! 73: } ! 74: } ! 75: ! 76: extern void raise_rls_interrupt( UART_STATE *asp ) ! 77: { ! 78: /* ! 79: * Check if receiver line status interrupt is enabled ! 80: */ ! 81: if (asp->int_enable_reg.bits.rx_line) ! 82: { ! 83: asp->receiver_line_status_interrupt_state = TRUE; ! 84: check_interrupt(asp); ! 85: } ! 86: } ! 87: ! 88: extern void raise_rda_interrupt( UART_STATE *asp ) ! 89: { ! 90: /* ! 91: * Check if data available interrupt is enabled ! 92: */ ! 93: if (asp->int_enable_reg.bits.data_available) ! 94: { ! 95: asp->data_available_interrupt_state = TRUE; ! 96: check_interrupt(asp); ! 97: } ! 98: } ! 99: ! 100: extern void raise_ms_interrupt( UART_STATE *asp ) ! 101: { ! 102: /* ! 103: * Check if modem status interrupt is enabled ! 104: */ ! 105: if (asp->int_enable_reg.bits.modem_status) ! 106: { ! 107: asp->modem_status_interrupt_state = TRUE; ! 108: check_interrupt(asp); ! 109: } ! 110: asp->modem_status_changed = TRUE; ! 111: } ! 112: ! 113: extern void raise_thre_interrupt( UART_STATE *asp ) ! 114: { ! 115: /* ! 116: * Check if tx holding register empty interrupt is enabled ! 117: */ ! 118: if (asp->int_enable_reg.bits.tx_holding) ! 119: { ! 120: asp->tx_holding_register_empty_interrupt_state = TRUE; ! 121: check_interrupt(asp); ! 122: } ! 123: } ! 124: ! 125: ! 126: /* ! 127: * ===================================================================== ! 128: * Subsidiary functions - for data available ! 129: * ===================================================================== ! 130: */ ! 131: ! 132: /* ! 133: * signal all characters transmitted! ! 134: */ ! 135: void clear_tbr_flag( UART_STATE *asp ) ! 136: { ! 137: asp->line_status_reg.bits.tx_shift_empty = 1; ! 138: } ! 139: ! 140: /* ! 141: * check for data available and line status changes ! 142: */ ! 143: static void check_data_available( tAdapter adapter ) ! 144: { ! 145: UART_STATE *asp = & UART_ADAPTER(adapter); ! 146: DWORD error; ! 147: ! 148: if (!asp->loopback_state) ! 149: { ! 150: if (!asp->line_status_reg.bits.data_ready) ! 151: { ! 152: if (!(asp->line_status_reg.bits.data_ready = host_com_read_rx( adapter, &asp->rx_buff_reg )) ! 153: && asp->int_enable_reg.bits.data_available) ! 154: { ! 155: host_com_rx_wait( adapter ); ! 156: } ! 157: } ! 158: ! 159: if ((error = host_com_get_error( adapter )) != 0) ! 160: { ! 161: /* ! 162: * Set line status register and raise line status interrupt ! 163: */ ! 164: if (error & (CE_OVERRUN | CE_RXOVER)) ! 165: asp->line_status_reg.bits.overrun_error = 1; ! 166: ! 167: if (error & CE_FRAME) ! 168: asp->line_status_reg.bits.framing_error = 1; ! 169: ! 170: if (error & CE_RXPARITY) ! 171: asp->line_status_reg.bits.parity_error = 1; ! 172: ! 173: if (error & CE_BREAK) ! 174: asp->line_status_reg.bits.break_interrupt = 1; ! 175: ! 176: raise_rls_interrupt( asp ); ! 177: } ! 178: } ! 179: } ! 180: ! 181: ! 182: /* ! 183: * flush all received input ! 184: */ ! 185: static void com_flush_input(tAdapter adapter) ! 186: { ! 187: BYTE dummy; ! 188: ! 189: while (host_com_read_rx( adapter, &dummy )) ! 190: /* do nothing */; ! 191: ! 192: UART_ADAPTER(adapter).line_status_reg.bits.data_ready = FALSE; ! 193: } ! 194: ! 195: /* ! 196: * set the IIR for current interrupts pending ! 197: */ ! 198: static BYTE generate_iir( tAdapter adapter ) ! 199: { ! 200: UART_STATE *asp = & UART_ADAPTER(adapter); ! 201: ! 202: /* ! 203: * Set up interrupt identification register with highest priority ! 204: * pending interrupt. ! 205: */ ! 206: ! 207: check_data_available( adapter ); ! 208: ! 209: return ! 210: (asp->receiver_line_status_interrupt_state) ? UART_RLS_INT ! 211: : (asp->line_status_reg.bits.data_ready) ? UART_RDA_INT ! 212: : (asp->tx_holding_register_empty_interrupt_state) ? UART_THRE_INT ! 213: : (asp->modem_status_interrupt_state) ? UART_MS_INT ! 214: : UART_NO_INT; ! 215: } ! 216: ! 217: ! 218: /* ! 219: * set modem status register to new status ! 220: */ ! 221: static void set_modem_status( tAdapter adapter, long modem_status ) ! 222: { ! 223: UART_STATE *asp = & UART_ADAPTER( adapter ); ! 224: int cts_state, dsr_state, rlsd_state, ri_state; ! 225: ! 226: cts_state = ((modem_status & HOST_MS_CTS) != 0); ! 227: dsr_state = ((modem_status & HOST_MS_DSR) != 0); ! 228: rlsd_state = ((modem_status & HOST_MS_RLSD) != 0); ! 229: ri_state = ((modem_status & HOST_MS_RI) != 0); ! 230: ! 231: /* ! 232: * Establish CTS state ! 233: */ ! 234: if (cts_state != asp->modem_status_reg.bits.CTS) ! 235: { ! 236: asp->modem_status_reg.bits.CTS = cts_state; ! 237: asp->modem_status_reg.bits.delta_CTS = TRUE; ! 238: raise_ms_interrupt(asp); ! 239: } ! 240: ! 241: /* ! 242: * Establish DSR state ! 243: */ ! 244: if (dsr_state != asp->modem_status_reg.bits.DSR) ! 245: { ! 246: asp->modem_status_reg.bits.DSR = dsr_state; ! 247: asp->modem_status_reg.bits.delta_DSR = TRUE; ! 248: raise_ms_interrupt(asp); ! 249: } ! 250: ! 251: /* ! 252: * Establish RLSD state ! 253: */ ! 254: if (rlsd_state != asp->modem_status_reg.bits.RLSD) ! 255: { ! 256: asp->modem_status_reg.bits.RLSD = rlsd_state; ! 257: asp->modem_status_reg.bits.delta_RLSD = TRUE; ! 258: raise_ms_interrupt(asp); ! 259: } ! 260: ! 261: /* ! 262: * Establish RI state ! 263: */ ! 264: if (ri_state != asp->modem_status_reg.bits.RI) ! 265: { ! 266: if ((asp->modem_status_reg.bits.RI = ri_state) == FALSE) ! 267: { ! 268: asp->modem_status_reg.bits.TERI = TRUE; ! 269: raise_ms_interrupt(asp); ! 270: } ! 271: } ! 272: } ! 273: ! 274: /* ! 275: * One of the modem control input lines has changed state ! 276: */ ! 277: static void refresh_modem_status( tAdapter adapter ) ! 278: { ! 279: /* ! 280: * Update the modem status register after a change to one of the ! 281: * modem status input lines ! 282: */ ! 283: UART_STATE *asp = & UART_ADAPTER(adapter); ! 284: ! 285: if (! UART_ADAPTER(adapter).loopback_state) ! 286: { ! 287: /* get current modem input state */ ! 288: set_modem_status( adapter, host_com_ioctl( adapter, HOST_COM_MSTATUS, 0 ) ); ! 289: } ! 290: } ! 291: ! 292: ! 293: /* ! 294: * ===================================================================== ! 295: * Subsidiary functions - for setting comms parameters ! 296: * ===================================================================== ! 297: */ ! 298: ! 299: static void set_baud_rate( tAdapter adapter ) ! 300: { ! 301: const long UART_bit_clock = 115200; ! 302: UART_STATE *asp = & UART_ADAPTER(adapter); ! 303: ! 304: if (UART_ADAPTER(adapter).divisor_latch.all != 0) ! 305: { ! 306: com_flush_input( adapter ); ! 307: host_com_ioctl( adapter, ! 308: HOST_COM_BAUD, ! 309: UART_bit_clock / UART_ADAPTER(adapter).divisor_latch.all ! 310: ); ! 311: } ! 312: } ! 313: ! 314: static void set_break( tAdapter adapter ) ! 315: { ! 316: /* ! 317: * Process the set break control bit. Bit 6 of the Line Control ! 318: * Register. ! 319: */ ! 320: UART_STATE *asp = & UART_ADAPTER(adapter); ! 321: ! 322: if (asp->line_control_reg.bits.set_break != asp->break_state ) ! 323: { ! 324: asp->break_state = asp->line_control_reg.bits.set_break; ! 325: host_com_ioctl( adapter, HOST_COM_SBRK, 0 ); ! 326: } ! 327: } ! 328: ! 329: static void set_line_control( tAdapter adapter ) ! 330: { ! 331: /* ! 332: * Set Number of data bits ! 333: * Parity bits ! 334: * Number of stop bits ! 335: */ ! 336: UART_STATE *asp = & UART_ADAPTER(adapter); ! 337: int host_line_ctrl; ! 338: const int host_bits[4][2] = ! 339: { HOST_LC_DATA_5 | HOST_LC_STOP_1, ! 340: HOST_LC_DATA_5 | HOST_LC_STOP_15, ! 341: HOST_LC_DATA_6 | HOST_LC_STOP_1, ! 342: HOST_LC_DATA_6 | HOST_LC_STOP_2, ! 343: HOST_LC_DATA_7 | HOST_LC_STOP_1, ! 344: HOST_LC_DATA_7 | HOST_LC_STOP_2, ! 345: HOST_LC_DATA_8 | HOST_LC_STOP_1, ! 346: HOST_LC_DATA_8 | HOST_LC_STOP_2}; ! 347: ! 348: host_line_ctrl = ! 349: ! 350: // the number of data bits ! 351: host_bits[asp->line_control_reg.bits.word_length] ! 352: ! 353: // and stop bits ! 354: [asp->line_control_reg.bits.no_of_stop_bits] ! 355: ! 356: // and the parity settings ! 357: | ((asp->line_control_reg.bits.parity_enabled == UART_PARITY_OFF) ! 358: ? HOST_LC_PARITY_NONE ! 359: ! 360: : (asp->line_control_reg.bits.stick_parity == UART_PARITY_STICK) ! 361: ? (asp->line_control_reg.bits.even_parity == UART_PARITY_ODD) ! 362: ? HOST_LC_PARITY_MARK ! 363: ! 364: : HOST_LC_PARITY_SPACE ! 365: ! 366: : (asp->line_control_reg.bits.even_parity == UART_PARITY_ODD) ! 367: ? HOST_LC_PARITY_ODD ! 368: ! 369: : HOST_LC_PARITY_EVEN ! 370: ); ! 371: ! 372: host_com_ioctl(adapter, HOST_COM_LINE_CTRL, host_line_ctrl); ! 373: } ! 374: ! 375: void set_modem_control( tAdapter adapter ) ! 376: { ! 377: UART_STATE *asp = & UART_ADAPTER( adapter ); ! 378: ! 379: /* ! 380: * Process the loopback control bit ! 381: */ ! 382: ! 383: if (asp->modem_control_reg.bits.loop != asp->loopback_state) ! 384: { ! 385: if (!(asp->loopback_state = asp->modem_control_reg.bits.loop)) ! 386: { ! 387: /* ! 388: * Reset the modem status inputs according to the real ! 389: * modem status ! 390: */ ! 391: refresh_modem_status( adapter ); ! 392: } ! 393: } ! 394: ! 395: /* ! 396: * Modem control function depends on the loopback control bit ! 397: */ ! 398: ! 399: if (asp->loopback_state) ! 400: { ! 401: set_modem_status( adapter, ! 402: ! 403: // loop DTR back to DSR ! 404: (asp->modem_control_reg.bits.DTR && HOST_MS_DSR) ! 405: ! 406: // loop RTS back to CTS ! 407: | (asp->modem_control_reg.bits.RTS && HOST_MS_CTS) ! 408: ! 409: // loop OUT1 back to RI ! 410: | (asp->modem_control_reg.bits.OUT1 && HOST_MS_RI) ! 411: ! 412: // loop OUT2 back to RLSD ! 413: | (asp->modem_control_reg.bits.OUT2 && HOST_MS_RLSD) ); ! 414: ! 415: } ! 416: else // not in loopback state ! 417: { ! 418: int host_modem_control = ! 419: (asp->modem_control_reg.bits.DTR ? HOST_MC_DTR : 0) ! 420: | (asp->modem_control_reg.bits.RTS ? HOST_MC_RTS : 0); ! 421: ! 422: /* ! 423: * In the real adapter, the OUT1 control bit is not connected ! 424: * so no real modem control change is required ! 425: */ ! 426: ! 427: /* ! 428: * In the real adapter the OUT2 control bit is used to determine ! 429: * whether the communications card can send interrupts; so no ! 430: * real modem control change is required ! 431: */ ! 432: asp->out2_state = asp->modem_control_reg.bits.OUT2; ! 433: ! 434: if (asp->modem_ctrl_state != host_modem_control) ! 435: { ! 436: asp->modem_ctrl_state = host_modem_control; ! 437: host_com_ioctl( adapter, HOST_COM_MODEM_CTRL, host_modem_control ); ! 438: } ! 439: } ! 440: } ! 441: ! 442: void com_reset(tAdapter adapter) ! 443: { ! 444: /* ! 445: * Set host devices to current state ! 446: */ ! 447: set_baud_rate( adapter ); ! 448: set_line_control( adapter ); ! 449: set_break( adapter ); ! 450: set_modem_control( adapter ); ! 451: } ! 452: ! 453: static int port_start[4] = {PC_COM1_PORT_START, ! 454: PC_COM2_PORT_START, ! 455: PC_COM3_PORT_START, ! 456: PC_COM4_PORT_START}; ! 457: static int port_end[4] = {PC_COM1_PORT_END, ! 458: PC_COM2_PORT_END, ! 459: PC_COM3_PORT_END, ! 460: PC_COM4_PORT_END}; ! 461: static int int_pri[4] = {PC_COM1_INT, ! 462: PC_COM2_INT, ! 463: PC_COM3_INT, ! 464: PC_COM4_INT}; ! 465: static int timeout[4] = {PC_COM1_TIMEOUT, ! 466: PC_COM2_TIMEOUT, ! 467: PC_COM3_TIMEOUT, ! 468: PC_COM4_TIMEOUT}; ! 469: ! 470: void com_init( tAdapter adapter ) ! 471: { ! 472: UART_STATE *asp = & UART_ADAPTER(adapter); ! 473: ! 474: asp->had_first_read = FALSE; ! 475: asp->hw_interrupt_priority = int_pri[adapter]; ! 476: ! 477: /* ! 478: * Set default state of all adapter registers ! 479: */ ! 480: asp->int_enable_reg.all = 0; ! 481: ! 482: asp->line_control_reg.all = 0; ! 483: asp->line_control_reg.bits.word_length = 3; ! 484: ! 485: asp->line_status_reg.all = 0; ! 486: asp->line_status_reg.bits.tx_holding_empty = 1; ! 487: asp->line_status_reg.bits.tx_shift_empty = 1; ! 488: ! 489: asp->break_state = FALSE; ! 490: ! 491: /* ! 492: * set up modem control reg so set_modem_control ! 493: * will set host adapter to the reset state ! 494: */ ! 495: asp->modem_control_reg.all = 0; ! 496: ! 497: asp->modem_control_reg.bits.DTR = TRUE; ! 498: asp->modem_control_reg.bits.RTS = TRUE; ! 499: asp->modem_control_reg.bits.OUT1 = TRUE; ! 500: asp->modem_control_reg.bits.OUT2 = TRUE; ! 501: ! 502: asp->modem_ctrl_state = 0; // different from DTR & RTS ! 503: asp->loopback_state = FALSE; ! 504: asp->divisor_latch_state = asp->line_control_reg.bits.DLAB; ! 505: ! 506: asp->modem_status_reg.all = 0; ! 507: asp->modem_status_changed = TRUE; ! 508: ! 509: /* ! 510: * Set up default state of our state variables ! 511: */ ! 512: ! 513: asp->receiver_line_status_interrupt_state = FALSE; ! 514: asp->data_available_interrupt_state = FALSE; ! 515: asp->tx_holding_register_empty_interrupt_state = FALSE; ! 516: asp->modem_status_interrupt_state = FALSE; ! 517: ! 518: check_interrupt( asp ); /* sets interrupt line state */ ! 519: ! 520: return; ! 521: } ! 522: ! 523: void com_close(tAdapter adapter) ! 524: { ! 525: } ! 526: ! 527: ! 528: /* ! 529: * ===================================================================== ! 530: * The Adaptor functions ! 531: * ===================================================================== ! 532: */ ! 533: ! 534: static void inb_RBR( tAdapter adapter, BYTE *value ) ! 535: { ! 536: UART_STATE *asp = & UART_ADAPTER(adapter); ! 537: ! 538: if (asp->divisor_latch_state) ! 539: *value = asp->divisor_latch.byte.LSB; ! 540: else ! 541: { ! 542: host_com_lock(adapter); ! 543: ! 544: // ! 545: // Read of rx buffer ! 546: // ! 547: check_data_available( adapter ); // get char if available ! 548: ! 549: *value = asp->rx_buff_reg; ! 550: asp->line_status_reg.bits.data_ready = FALSE; // signal character read ! 551: ! 552: check_data_available( adapter ); // check next char ! 553: ! 554: asp->data_available_interrupt_state = ! 555: (asp->int_enable_reg.bits.data_available ! 556: && asp->line_status_reg.bits.data_ready); ! 557: check_interrupt(asp); // set interrupt line ! 558: ! 559: host_com_unlock(adapter); ! 560: } ! 561: } ! 562: ! 563: static void inb_IER( tAdapter adapter, BYTE *value ) ! 564: { ! 565: UART_STATE *asp = & UART_ADAPTER(adapter); ! 566: ! 567: if (asp->divisor_latch_state) ! 568: *value = asp->divisor_latch.byte.MSB; ! 569: else ! 570: *value = asp->int_enable_reg.all; ! 571: } ! 572: ! 573: static void inb_IIR( tAdapter adapter, BYTE *value ) ! 574: { ! 575: UART_STATE *asp = & UART_ADAPTER(adapter); ! 576: ! 577: host_com_lock( adapter ); ! 578: ! 579: if ((*value = generate_iir( adapter )) == UART_THRE_INT) ! 580: { ! 581: asp->tx_holding_register_empty_interrupt_state = FALSE; ! 582: check_interrupt( asp ); ! 583: } ! 584: ! 585: host_com_unlock(adapter); ! 586: } ! 587: ! 588: static void inb_LCR( tAdapter adapter, BYTE *value ) ! 589: { ! 590: *value = UART_ADAPTER(adapter).line_control_reg.all; ! 591: } ! 592: ! 593: static void inb_MCR( tAdapter adapter, BYTE *value ) ! 594: { ! 595: *value = UART_ADAPTER(adapter).modem_control_reg.all; ! 596: } ! 597: ! 598: static void inb_LSR( tAdapter adapter, BYTE *value ) ! 599: { ! 600: UART_STATE *asp = & UART_ADAPTER(adapter); ! 601: host_com_lock(adapter); ! 602: ! 603: *value = asp->line_status_reg.all; ! 604: ! 605: asp->line_status_reg.bits.overrun_error = 0; ! 606: asp->line_status_reg.bits.parity_error = 0; ! 607: asp->line_status_reg.bits.framing_error = 0; ! 608: asp->line_status_reg.bits.break_interrupt = 0; ! 609: asp->receiver_line_status_interrupt_state = FALSE; ! 610: check_interrupt(asp); ! 611: ! 612: host_com_unlock(adapter); ! 613: } ! 614: ! 615: static void inb_MSR( tAdapter adapter, BYTE *value ) ! 616: { ! 617: UART_STATE *asp = & UART_ADAPTER(adapter); ! 618: ! 619: if (!asp->modem_status_changed && !asp->loopback_state) ! 620: { ! 621: *value = asp->last_modem_status_value.all; ! 622: } ! 623: else ! 624: { ! 625: host_com_lock(adapter); ! 626: ! 627: if (asp->loopback_state) ! 628: { ! 629: *value = asp->modem_status_reg.all; ! 630: asp->modem_status_changed = TRUE; ! 631: } ! 632: else ! 633: { ! 634: refresh_modem_status( adapter ); ! 635: *value = asp->modem_status_reg.all; ! 636: asp->modem_status_changed = FALSE; ! 637: } ! 638: ! 639: asp->modem_status_reg.bits.delta_CTS = 0; ! 640: asp->modem_status_reg.bits.delta_DSR = 0; ! 641: asp->modem_status_reg.bits.delta_RLSD = 0; ! 642: asp->modem_status_reg.bits.TERI = 0; ! 643: asp->modem_status_interrupt_state = FALSE; ! 644: check_interrupt(asp); ! 645: asp->last_modem_status_value.all = asp->modem_status_reg.all; ! 646: ! 647: host_com_unlock(adapter); ! 648: } ! 649: } ! 650: ! 651: static void inb_SCR( tAdapter adapter, BYTE *value ) ! 652: { ! 653: *value = UART_ADAPTER(adapter).scratch; // Just read the value stored. ! 654: } ! 655: ! 656: void com_inb( WORD port, BYTE *value ) ! 657: { ! 658: void (*(inb_func[]))( int, BYTE * ) = ! 659: { ! 660: inb_RBR, ! 661: inb_IER, ! 662: inb_IIR, ! 663: inb_LCR, ! 664: inb_MCR, ! 665: inb_LSR, ! 666: inb_MSR, ! 667: inb_SCR ! 668: }; ! 669: tAdapter adapter = adapter_for_port(port); ! 670: ! 671: if (adapter < NUM_SERIAL_PORTS) ! 672: inb_func[port & 0x7] (adapter, value); ! 673: else ! 674: *value = 0xFF; ! 675: } ! 676: ! 677: ! 678: static void outb_THR( tAdapter adapter, BYTE value ) ! 679: { ! 680: const BYTE selectBits[4] = { 0x1f, 0x3f, 0x7f, 0xff } ; ! 681: UART_STATE *asp = & UART_ADAPTER(adapter); ! 682: ! 683: host_com_lock(adapter); ! 684: ! 685: if (asp->divisor_latch_state) ! 686: { ! 687: if (asp->divisor_latch.byte.LSB != value) ! 688: { ! 689: asp->divisor_latch.byte.LSB = value; ! 690: asp->baud_rate_changed = TRUE; ! 691: } ! 692: } ! 693: else ! 694: { ! 695: /* ! 696: * Write char to tx buffer ! 697: */ ! 698: if (!asp->loopback_state) ! 699: { ! 700: asp->line_status_reg.bits.tx_shift_empty = 0; ! 701: host_com_write_tx( adapter, value ); ! 702: } ! 703: else ! 704: { ! 705: /* Loopback case requires masking off */ ! 706: /* of bits based upon word length. */ ! 707: asp->rx_buff_reg = value ! 708: & selectBits[ asp->line_control_reg.bits.word_length ]; ! 709: ! 710: /* ! 711: * Check for data overrun and set up correct interrupt ! 712: */ ! 713: if ( asp->line_status_reg.bits.data_ready) ! 714: { ! 715: asp->line_status_reg.bits.overrun_error = TRUE; ! 716: raise_rls_interrupt(asp); ! 717: } ! 718: else ! 719: { ! 720: asp->line_status_reg.bits.data_ready = TRUE; ! 721: raise_rda_interrupt(asp); ! 722: } ! 723: asp->line_status_reg.bits.tx_shift_empty = 1; ! 724: } ! 725: ! 726: // holding register permanently empty!!! ! 727: asp->line_status_reg.bits.tx_holding_empty = 1; ! 728: raise_thre_interrupt( asp ); ! 729: } ! 730: ! 731: host_com_unlock(adapter); ! 732: } ! 733: ! 734: static void outb_IER( tAdapter adapter, BYTE value ) ! 735: { ! 736: UART_STATE *asp = & UART_ADAPTER(adapter); ! 737: host_com_lock(adapter); ! 738: ! 739: if (asp->divisor_latch_state) ! 740: { ! 741: if (asp->divisor_latch.byte.MSB != value) ! 742: { ! 743: asp->divisor_latch.byte.MSB = value; ! 744: asp->baud_rate_changed = TRUE; ! 745: } ! 746: } ! 747: else ! 748: { ! 749: int org_da = asp->int_enable_reg.bits.data_available; ! 750: ! 751: asp->int_enable_reg.all = value & 0xf; ! 752: ! 753: // ! 754: // Kill off any pending interrupts for those items ! 755: // which are set now as disabled ! 756: // ! 757: if (!asp->int_enable_reg.bits.data_available) ! 758: asp->data_available_interrupt_state = FALSE; ! 759: ! 760: if (!asp->int_enable_reg.bits.tx_holding) ! 761: asp->tx_holding_register_empty_interrupt_state = FALSE; ! 762: ! 763: if (!asp->int_enable_reg.bits.rx_line) ! 764: asp->receiver_line_status_interrupt_state = FALSE; ! 765: ! 766: if (!asp->int_enable_reg.bits.modem_status) ! 767: asp->modem_status_interrupt_state = FALSE; ! 768: ! 769: // ! 770: // Check for immediately actionable interrupts ! 771: // ! 772: check_data_available( adapter ); ! 773: if ( asp->line_status_reg.bits.data_ready == 1 ) ! 774: raise_rda_interrupt( asp ); ! 775: if ( asp->line_status_reg.bits.tx_holding_empty == 1 ) ! 776: raise_thre_interrupt( asp ); ! 777: ! 778: check_interrupt(asp); // lower int line if no outstanding interrupts ! 779: ! 780: } ! 781: ! 782: host_com_unlock(adapter); ! 783: } ! 784: ! 785: static void outb_IIR( tAdapter adapter, BYTE value ) ! 786: { ! 787: // ! 788: // Essentially a READ ONLY register ! 789: // ! 790: } ! 791: ! 792: static void outb_LCR( tAdapter adapter, BYTE value ) ! 793: { ! 794: const LINE_CONTROL_REG LCRFlushMask = ! 795: { ! 796: (unsigned) ~0, // word_length:2; ! 797: (unsigned) 0, // no_of_stop_bits:1; ! 798: (unsigned) ~0, // parity_enabled:1; ! 799: (unsigned) ~0, // even_parity:1; ! 800: (unsigned) ~0, // stick_parity:1; ! 801: (unsigned) 0, // set_break:1; ! 802: (unsigned) 0 // DLAB:1; ! 803: }; ! 804: UART_STATE *asp = & UART_ADAPTER(adapter); ! 805: ! 806: host_com_lock(adapter); ! 807: if (((value ^ asp->line_control_reg.all) & LCRFlushMask.all) != 0) ! 808: com_flush_input(adapter); ! 809: ! 810: if (asp->line_control_reg.all != value) ! 811: { ! 812: asp->line_control_reg.all = value; ! 813: set_line_control( adapter ); ! 814: } ! 815: ! 816: if (asp->divisor_latch_state != asp->line_control_reg.bits.DLAB) ! 817: { ! 818: asp->divisor_latch_state = asp->line_control_reg.bits.DLAB; ! 819: if (asp->divisor_latch_state) ! 820: asp->baud_rate_changed = FALSE; ! 821: else ! 822: { ! 823: if (asp -> baud_rate_changed) ! 824: { ! 825: set_baud_rate(adapter); ! 826: } ! 827: } ! 828: } ! 829: ! 830: set_break(adapter); ! 831: ! 832: host_com_unlock(adapter); ! 833: } ! 834: ! 835: static void outb_MCR( tAdapter adapter, BYTE value ) ! 836: { ! 837: UART_STATE *asp = & UART_ADAPTER(adapter); ! 838: host_com_lock(adapter); ! 839: ! 840: // Optimisation - DOS keeps re-writing this register ! 841: if ( asp->modem_control_reg.all != value ) ! 842: { ! 843: asp->modem_control_reg.all = value; ! 844: asp->modem_control_reg.bits.pad = 0; ! 845: ! 846: set_modem_control(adapter); ! 847: } ! 848: ! 849: host_com_unlock(adapter); ! 850: } ! 851: ! 852: static void outb_LSR( tAdapter adapter, BYTE value ) ! 853: { ! 854: UART_STATE *asp = & UART_ADAPTER(adapter); ! 855: int temp; ! 856: ! 857: host_com_lock(adapter); ! 858: ! 859: temp = asp->line_status_reg.bits.tx_shift_empty; /* READ ONLY */ ! 860: asp->line_status_reg.all = value; ! 861: asp->line_status_reg.bits.tx_shift_empty = temp; ! 862: ! 863: host_com_unlock(adapter); ! 864: } ! 865: ! 866: static void outb_MSR( tAdapter adapter, BYTE value ) ! 867: { ! 868: UART_STATE *asp = & UART_ADAPTER(adapter); ! 869: host_com_lock(adapter); ! 870: ! 871: // ! 872: // Essentially a READ ONLY register, except that DR-DOS ! 873: // writes to this reg after setting int on MSR change and ! 874: // expects to get an interrupt back!!! So we will oblige. ! 875: // Writing to this reg only seems to affect the delta bits ! 876: // (bits 0-3) of the reg. ! 877: // ! 878: if (((value ^ asp->modem_status_reg.all) & 0xf) != 0) ! 879: { ! 880: asp->modem_status_reg.all &= 0xf0; ! 881: asp->modem_status_reg.all |= value & 0xf; ! 882: if (!asp->loopback_state) ! 883: raise_ms_interrupt(asp); ! 884: } ! 885: ! 886: host_com_unlock(adapter); ! 887: } ! 888: ! 889: static void outb_SCR( tAdapter adapter, BYTE value ) ! 890: { ! 891: UART_STATE *asp = & UART_ADAPTER(adapter); ! 892: asp->scratch = value; // Scratch register - just store the value. ! 893: } ! 894: ! 895: void com_outb(WORD port, BYTE value) ! 896: { ! 897: void (*(outb_func[]))(int, BYTE) = ! 898: { ! 899: outb_THR, ! 900: outb_IER, ! 901: outb_IIR, ! 902: outb_LCR, ! 903: outb_MCR, ! 904: outb_LSR, ! 905: outb_MSR, ! 906: outb_SCR ! 907: }; ! 908: tAdapter adapter = adapter_for_port(port); ! 909: ! 910: if (adapter < NUM_SERIAL_PORTS) ! 911: { ! 912: outb_func[port & 0x7] (adapter, value); ! 913: } ! 914: } ! 915: ! 916: ! 917: /********************************************************/
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.