|
|
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.