Annotation of ntddk/src/vdd/com_vdd/pc_com.c, revision 1.1.1.1

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: /********************************************************/

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.