home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_09_12 / 9n12073a < prev    next >
Text File  |  1991-07-27  |  6KB  |  227 lines

  1. /** LISTING 2  ***** TERM.C *************************/
  2. #include <conio.h>
  3. #include <stdio.h>
  4. #include <time.h>
  5. #include <dos.h>
  6. #include "uart.h"
  7. #include "uartmacs.c"
  8.  
  9. /* Set to 1 by dummy interrupt machine if 
  10.    correct interrupt during port presence test */
  11. static char g_got_int_flag;             
  12.  
  13. /* Base address of port being tested */
  14. static unsigned int g_port_base_address;       
  15.  
  16. /*****************************************************
  17. rc = Test_for_asynch_port (port_address, irq_level )
  18.      int port_address - Base address of port to test 
  19.                         for
  20.      int irq_level - Interrupt level (3 - 7) that 
  21.                      port is supposed to be on
  22. rc = 1 : Port check passes
  23. rc = -1: Port check fails or IRQ out of range
  24. *****************************************************/
  25.  
  26. /* Enable stack probing for this function */
  27. #pragma check_stack(on)    
  28. int Test_for_asynch_port( unsigned int port_address, 
  29.                           unsigned int irq_level )
  30. {
  31.    int mask_save;                  
  32.    int new_mask;                   
  33.    unsigned int interrupt_number;  
  34.    static char a_funcname[] = 
  35.        "Test_for_asynch_port: ";
  36.    void (interrupt far * p_vec_saved)();       
  37.    time_t start_time;              
  38.    time_t time_now;                
  39.  
  40.    /* Validate range of irq level */
  41.    if ( (irq_level < 3) || ( irq_level > 7 ) ) 
  42.    {
  43.        fprintf(stderr,"%s bad irq level %u\n",
  44.            a_funcname,irq_level);
  45.        return(-1);
  46.    }
  47.  
  48.    /* Clear flag - we haven't gotten a successful 
  49.       interrupt yet. */
  50.    g_got_int_flag = 0;
  51.  
  52.    /* Save port address for interrupt routine */
  53.    g_port_base_address = port_address; 
  54.  
  55.    /* Make sure interrupt generation is disabled */
  56.    outp(port_address+INTERRUPT_ENABLE_REGISTER,0x00);
  57.  
  58.    /* Delay for port to catch up */
  59.    IO_DELAY(3);
  60.  
  61.    /* Clear interrupt identification  register */
  62.    inp(port_address+INTERRUPT_IDENT_REGISTER); 
  63.  
  64.    /* Delay for port to catch up */
  65.    IO_DELAY(3);
  66.  
  67.    /* Clear receive register. */
  68.    inp(port_address+RECEIVE_REGISTER);
  69.  
  70.    /* Delay for port to catch up */
  71.    IO_DELAY(3);
  72.  
  73.    /* Clear line status interrupt */
  74.    inp(port_address+LINE_STATUS_REGISTER);
  75.  
  76.    /* Delay for port to catch up */
  77.    IO_DELAY(3);
  78.  
  79.    /* Clear modem status interrupt */
  80.    inp(port_address+MODEM_STATUS_REGISTER);
  81.  
  82.    /* Calculate interrupt number */
  83.    interrupt_number = 0x08 + irq_level;
  84.  
  85.    /* Save current interrupt vector */
  86.    p_vec_saved = _dos_getvect(interrupt_number);
  87.  
  88.    _disable();         /* disable interrupts */
  89.  
  90.    /* Latch test interrupt routine into vector */
  91.    _dos_setvect(interrupt_number,
  92.        Catch_asynch_test_interrupt);
  93.  
  94.    /* Save current 8259 state and enable this 
  95.       interrupt */
  96.    mask_save = inp(R8259A_MASK);     
  97.    new_mask = ((int) 
  98.        ( 0xffff ^ ( 0x0001 << irq_level) )) & 
  99.        mask_save;
  100.  
  101.    /* Delay for port to catch up */
  102.    IO_DELAY(3);
  103.  
  104.    /* Output new mask to 8259 interrupt controller */
  105.    outp(R8259A_MASK,new_mask);      
  106.  
  107.    /* Delay for port to catch up */
  108.    IO_DELAY(3);
  109.  
  110.    _enable();                      /* Enable interrupts */
  111.     
  112.    /* Activate OUT2 to enable interrupt generation by 
  113.       the UART */
  114.    outp(port_address+MODEM_CONTROL_REGISTER,0x08);
  115.  
  116.    /* Delay for port to catch up */
  117.    IO_DELAY(3);
  118.  
  119.    /* Enable generation of THRE interrupt */
  120.    outp(port_address+INTERRUPT_ENABLE_REGISTER,0x02);
  121.  
  122.  
  123.    /* Save start time */
  124.    time(&start_time);
  125.  
  126.    /* Loop until flag indicating receipt of interrupt 
  127.       has been set (up to 3 seconds) */
  128.    while ( g_got_int_flag == 0 )
  129.    {
  130.        /* If more than 3 seconds have passed, 
  131.           stop waiting */
  132.        time(&time_now);
  133.        if ( (time_now - start_time) > 3)
  134.            break;
  135.    }
  136.  
  137.    /* Make sure interrupt generation is disabled */
  138.    outp(port_address+INTERRUPT_ENABLE_REGISTER,0x00);
  139.  
  140.    /* Delay for port to catch up */
  141.    IO_DELAY(3);
  142.  
  143.    /* Deactivate OUT2 to disable interrupt generation 
  144.       by UART */
  145.    outp(port_address+MODEM_CONTROL_REGISTER,0x00);
  146.  
  147.    /* Delay for port to catch up */
  148.    IO_DELAY(3);
  149.  
  150.    /* Clear interrupt identification  register */
  151.    inp(port_address+INTERRUPT_IDENT_REGISTER); 
  152.  
  153.    /* Delay for port to catch up */
  154.    IO_DELAY(3);
  155.  
  156.    /* Clear receive register. */
  157.    inp(port_address+RECEIVE_REGISTER);
  158.  
  159.    /* Delay for port to catch up */
  160.    IO_DELAY(3);
  161.  
  162.    /* Clear line status interrupt */
  163.    inp(port_address+LINE_STATUS_REGISTER);
  164.  
  165.    /* Delay for port to catch up */
  166.    IO_DELAY(3);
  167.  
  168.    /* Clear modem status interrupt */
  169.    inp(port_address+MODEM_STATUS_REGISTER);
  170.  
  171.    _disable();                     /* Disable interrupts */
  172.  
  173.    /* Restore 8259 state */
  174.    outp(R8259A_MASK,mask_save);      
  175.  
  176.    /* Restore interrupt vector */
  177.    _dos_setvect(interrupt_number,p_vec_saved);
  178.  
  179.    _enable();
  180.  
  181.    if ( g_got_int_flag == 1)
  182.        return(1);
  183.    else
  184.        return(-1);
  185. }
  186. /* Disable stack probing for interrupt catcher */
  187. #pragma check_stack(off)
  188. void interrupt far Catch_asynch_test_interrupt(void)
  189. {
  190.    register int value_from_port;   
  191.  
  192.    _disable();     /* Disable all interrupts */
  193.  
  194.    /* read port's interrupt identification register */
  195.    value_from_port = inp(g_port_base_address+
  196.                          INTERRUPT_IDENT_REGISTER);
  197.  
  198.    if ( !(value_from_port & 0x01) )  
  199.    {   /* There is an interrupt pending */
  200.        if (value_from_port & 0x02) 
  201.        {   /* interrupt for transmit holding 
  202.               register empty */
  203.  
  204.            /* Read the port's line status register and 
  205.               check for THRE just to double check */
  206.            value_from_port = inp(g_port_base_address +
  207.                                 LINE_STATUS_REGISTER);
  208.            if ( value_from_port & 0x20 )
  209.               /* We have succeeded! Set global 
  210.                  flag. */
  211.               g_got_int_flag = 1;       
  212.  
  213.        }
  214.    }
  215.  
  216.    /* Output End Of Interrupt to interrupt 
  217.       controller */
  218.    outp(R8259A_CONTROL,0x20);        
  219.  
  220.    /* Note - Interrupts are not re-enabled to ensure 
  221.              that the IRET will be executed before 
  222.              the next interrupt */
  223.  
  224.    return;
  225. }
  226.  
  227.