home *** CD-ROM | disk | FTP | other *** search
/ Over 1,000 Doom Levels / 1000DOOMLevels-3DSharewareGames.bin / pc / doomfaqs / ser4_src / port.c < prev    next >
C/C++ Source or Header  |  1994-03-19  |  9KB  |  460 lines

  1. // port.c
  2.  
  3. #include "doomnet.h"
  4. #include "sersetup.h"
  5.  
  6. void jump_start( void );
  7.  
  8. void interrupt isr_8250 (void);
  9. void interrupt isr_16550 (void);
  10.  
  11. union    REGS    regs;
  12. struct    SREGS    sregs;
  13.  
  14. que_t        inque, outque;
  15.  
  16.  
  17. enum {UART_8250, UART_16550} uart_type;
  18. extern int uart;            // io address
  19. extern int irq;
  20. extern unsigned long baud;
  21.  
  22. int            modem_status = -1;
  23. int            line_status = -1;
  24.  
  25. void interrupt (*oldirqvect) (void);
  26. int            irqintnum;
  27.  
  28. extern int comport;
  29.  
  30.  
  31. /* showUartErrors() counters. */
  32. extern unsigned long numBreak;
  33. extern unsigned long numFramingError;
  34. extern unsigned long numParityError;
  35. extern unsigned long numOverrunError;
  36. extern unsigned long numTxInterrupts;
  37. extern unsigned long numRxInterrupts;
  38.  
  39.  
  40. /*
  41. ==============
  42. =
  43. = GetUart
  44. =
  45. ==============
  46. */
  47.  
  48. void GetUart (void)
  49. {
  50.     char   far *system_data;
  51.     static int ISA_uarts[] = {0x3f8,0x2f8,0x3e8,0x2e8};
  52.     static int ISA_IRQs[] = {4,3,4,3};
  53.     static int MCA_uarts[] = {0x03f8,0x02f8,0x3220,0x3228};
  54.     static int MCA_IRQs[] = {4,3,3,3};
  55.  
  56.     regs.h.ah = 0xc0;
  57.     int86x( 0x15, ®s, ®s, &sregs );
  58.     if ( regs.x.cflag )
  59.     {
  60.         if (irq == -1)
  61.             irq = ISA_IRQs[ comport-1 ];
  62.         if (uart == -1)
  63.             uart = ISA_uarts[ comport-1 ];
  64.         return;
  65.     }
  66.     system_data = ( char far *) ( ( (long) sregs.es << 16 ) + regs.x.bx );
  67.     if ( system_data[ 5 ] & 0x02 )
  68.     {
  69.         if (irq == -1)
  70.             irq = MCA_IRQs[ comport-1 ];
  71.         if (uart == -1)
  72.             uart = MCA_uarts[ comport-1 ];
  73.     }
  74.     else
  75.     {
  76.         if (irq == -1)
  77.             irq = ISA_IRQs[ comport-1 ];
  78.         if (uart == -1)
  79.             uart = ISA_uarts[ comport-1 ];
  80.     }
  81.  
  82.     printf ("Looking for UART at port 0x%x, irq %d...\n\n",uart,irq);
  83. }
  84.  
  85.  
  86.  
  87.  
  88. /*
  89. ===============
  90. =
  91. = InitPort
  92. =
  93. ===============
  94. */
  95.  
  96. void InitPort (void)
  97. {
  98.     int mcr;
  99.     int    temp;
  100.     unsigned long divisor;
  101.  
  102. //
  103. // init com port settings
  104. //
  105.  
  106. /*******
  107.     regs.x.ax = 0xf3;        //f3= 9600 n 8 1
  108.     regs.x.dx = comport - 1;
  109.     int86 (0x14, ®s, ®s);
  110. *******/
  111.  
  112.     if ((divisor = baud) == 14400)
  113.         divisor = 19200;
  114.  
  115.     divisor = CLOCK_FREQUENCY / (16 * divisor);                    /* Calc. divisor */
  116.     OUTPUT( uart + LINE_CONTROL_REGISTER, LCR_DLAB );            /* Enable divisor */
  117.     OUTPUT( uart + DIVISOR_LATCH_HIGH, 0 );                        /* Set divisor */
  118.     OUTPUT( uart + DIVISOR_LATCH_LOW, (unsigned char) divisor);
  119.     OUTPUT( uart + LINE_CONTROL_REGISTER, 3 );                    /* Set 8,n,1 */
  120.  
  121. //
  122. // check for a 16550
  123. //
  124.     OUTPUT( uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE + FCR_TRIGGER_04 );
  125.     temp = INPUT( uart + INTERRUPT_ID_REGISTER );
  126.     if ( ( temp & 0xf8 ) == 0xc0 )
  127.     {
  128.         uart_type = UART_16550;
  129.         printf ("UART is a 16550\n\n");
  130.     }
  131.     else
  132.     {
  133.         uart_type = UART_8250;
  134.         OUTPUT( uart + FIFO_CONTROL_REGISTER, 0 );
  135.         printf ("UART is an 8250\n\n");
  136.     }
  137.  
  138. //
  139. // prepare for interrupts
  140. //
  141.     OUTPUT( uart + INTERRUPT_ENABLE_REGISTER, 0 );    /* Turn off interrupts */
  142.  
  143.     mcr = INPUT( uart + MODEM_CONTROL_REGISTER );    /* Get modem status */
  144.     mcr |= MCR_OUT2;                                            /* Set GPO 2 */
  145.     mcr &= ~MCR_LOOPBACK;                                    /* Turn off loopback test */
  146.     mcr |= MCR_DTR;                                            /* Set DTR */
  147.     mcr |= MCR_RTS;                                            /* Set RTS */
  148.     OUTPUT( uart + MODEM_CONTROL_REGISTER, mcr );    /* Set modem status */
  149.  
  150.     INPUT( uart );                                                /* Clear Rx interrupts */
  151.     INPUT( uart + INTERRUPT_ID_REGISTER );                /* Clear Tx interrupts */
  152.  
  153. //
  154. // hook the irq vector
  155. //
  156.     irqintnum = irq + 8;
  157.  
  158.     oldirqvect = getvect (irqintnum);
  159.     if( uart_type == UART_8250 )            /* Use different interrupt routines */
  160.         setvect (irqintnum, isr_8250);
  161.     else
  162.         setvect (irqintnum, isr_16550);
  163.  
  164.     OUTPUT( 0x20 + 1, INPUT( 0x20 + 1 ) & ~(1<<irq) );
  165.  
  166.     CLI();
  167.  
  168. // enable RX and TX interrupts at the uart
  169. // also enable Line Status interrupts to watch for errors.
  170.  
  171.     OUTPUT( uart + INTERRUPT_ENABLE_REGISTER,
  172.         IER_RX_DATA_READY + IER_TX_HOLDING_REGISTER_EMPTY + IER_LINE_STATUS );
  173.  
  174. // enable interrupts through the interrupt controller
  175.  
  176.     OUTPUT( 0x20, 0xc2 );
  177.  
  178.  
  179.     STI();
  180.  
  181.  
  182. }
  183.  
  184.  
  185. /*
  186. =============
  187. =
  188. = ShutdownPort
  189. =
  190. =============
  191. */
  192.  
  193. void ShutdownPort ( void )
  194. {
  195.     OUTPUT( uart + INTERRUPT_ENABLE_REGISTER, 0 );    /* Turn off interrupts */
  196.     OUTPUT( uart + MODEM_CONTROL_REGISTER, 0 );        /* Clear modem status */
  197.     OUTPUT( uart + FIFO_CONTROL_REGISTER, 0 );        /* Clear fifo status */
  198.  
  199.     OUTPUT( 0x20 + 1, INPUT( 0x20 + 1 ) | (1<<irq) );
  200.  
  201.     setvect (irqintnum,oldirqvect);                        /* Return to orig. inter. */
  202.  
  203. #if 0   /* Leave port as it is. */
  204. *
  205. *    regs.x.ax = 0xf3;        //f3= 9600 n 8 1
  206. *    regs.x.dx = comport - 1;
  207. *    int86 (0x14, ®s, ®s);
  208. *
  209. #endif
  210.  
  211. }
  212.  
  213.  
  214. int read_byte( void )
  215. {
  216.    int   c;
  217.  
  218.    if (inque.size == 0)
  219.       return -1;
  220.  
  221.    c = inque.data[inque.tail++];
  222.    inque.size--;
  223.  
  224.    if (inque.tail >= QUESIZE)
  225.       inque.tail = 0;      // wrap around
  226.  
  227.    return c;
  228. }
  229.  
  230.  
  231. void write_byte( unsigned char c )
  232. {
  233.    outque.data[outque.head++] = c;
  234.    outque.size++;
  235.  
  236.    if (outque.head >= QUESIZE)
  237.       outque.head = 0;     // wrap around
  238. }
  239.  
  240.  
  241. void write_bytes( char *buf, int count )
  242. {
  243.    if (outque.head + count >= QUESIZE)                        /* About to wrap around */
  244.    {
  245.       while (count--)
  246.          write_byte (*buf++);
  247.    }
  248.    else
  249.    {
  250.       memcpy(outque.data + outque.head, buf, count);    /* Write all at once */
  251.       outque.head += count;
  252.       outque.size += count;
  253.    }
  254. }
  255.  
  256.  
  257.  
  258. //==========================================================================
  259. /*
  260. ==============
  261. =
  262. = isr_8250
  263. =
  264. ==============
  265. */
  266.  
  267. void interrupt isr_8250(void)
  268. {
  269.     int c;
  270.     int    count;
  271.  
  272.     while (1)
  273.     {
  274.         switch( INPUT( uart + INTERRUPT_ID_REGISTER ) & 7 )
  275.         {
  276.  
  277. //
  278. // receive exactly one byte, since this is a UART 8250
  279. //
  280.         case IIR_RX_DATA_READY_INTERRUPT :
  281. //I_ColorBlack (0,63,0);
  282.             ++numRxInterrupts;
  283.             c = INPUT( uart + RECEIVE_BUFFER_REGISTER );
  284.             inque.data[inque.head++] = c;
  285.             inque.size++;
  286.             if (inque.head >= QUESIZE)
  287.                 inque.head = 0;      // wrap around
  288.             break;
  289.  
  290. //
  291. // transmit exactly one byte, since this is a UART 8250
  292. //
  293.         case IIR_TX_HOLDING_REGISTER_INTERRUPT :
  294. //I_ColorBlack (63,0,0);
  295.             ++numTxInterrupts;
  296.             if (outque.size != 0)
  297.             {
  298.                 c = outque.data[outque.tail++];
  299.                 outque.size--;
  300.                 if (outque.tail >= QUESIZE)
  301.                     outque.tail = 0;      // wrap around
  302.                 OUTPUT( uart + TRANSMIT_HOLDING_REGISTER, c );
  303.             }
  304.             break;
  305.  
  306. #if 0        // not enabled
  307. *        case IIR_MODEM_STATUS_INTERRUPT :
  308. *            modem_status = INPUT( uart + MODEM_STATUS_REGISTER );
  309. *            break;
  310. #endif
  311.  
  312. //
  313. // line status
  314. //
  315.         case IIR_LINE_STATUS_INTERRUPT :
  316.             line_status = INPUT( uart + LINE_STATUS_REGISTER );
  317.  
  318.             if ( line_status & LSR_OVERRUN_ERROR )
  319.                 ++numOverrunError;
  320.  
  321.             if ( line_status & LSR_PARITY_ERROR )
  322.                 ++numParityError;
  323.  
  324.             if ( line_status & LSR_FRAMING_ERROR )
  325.                 ++numFramingError;
  326.  
  327.             if ( line_status & LSR_BREAK_DETECT )
  328.                 ++numBreak;
  329.  
  330.             break;
  331.  
  332. //
  333. // done
  334. //
  335.         default :
  336. //I_ColorBlack (0,0,0);
  337.             OUTPUT( 0x20, 0x20 );
  338.             return;
  339.         }
  340.     }
  341. }
  342.  
  343. //==========================================================================
  344. /*
  345. ==============
  346. =
  347. = isr_16550
  348. =
  349. ==============
  350. */
  351.  
  352. void interrupt isr_16550(void)
  353. {
  354.     int c;
  355.     int    count;
  356.  
  357.     while (1)
  358.     {
  359.         switch( INPUT( uart + INTERRUPT_ID_REGISTER ) & 7 )
  360.         {
  361. //
  362. // receive
  363. //
  364.         case IIR_RX_DATA_READY_INTERRUPT :
  365. //I_ColorBlack (0,63,0);
  366.             ++numRxInterrupts;
  367.             do
  368.             {
  369.                 c = INPUT( uart + RECEIVE_BUFFER_REGISTER );
  370.             inque.data[inque.head++] = c;
  371.             inque.size++;
  372.             if (inque.head >= QUESIZE)
  373.                inque.head = 0;      // wrap around
  374.             } while ( INPUT( uart + LINE_STATUS_REGISTER ) & LSR_DATA_READY );
  375.  
  376.             break;
  377.  
  378. //
  379. // transmit
  380. //
  381.         case IIR_TX_HOLDING_REGISTER_INTERRUPT :
  382. //I_ColorBlack (63,0,0);
  383.             ++numTxInterrupts;
  384.             if (outque.size != 0)
  385.             {
  386.                 count = 16;
  387.                 do
  388.                 {
  389.                c = outque.data[outque.tail++];
  390.                outque.size--;
  391.                if (outque.tail >= QUESIZE)
  392.                   outque.tail = 0;      // wrap around
  393.  
  394.                     OUTPUT( uart + TRANSMIT_HOLDING_REGISTER, c );
  395.                 } while (--count && outque.size != 0);
  396.             }
  397.             break;
  398.  
  399. #if 0        // not enabled
  400. *        case IIR_MODEM_STATUS_INTERRUPT :
  401. *            modem_status = INPUT( uart + MODEM_STATUS_REGISTER );
  402. *            break;
  403. #endif
  404.  
  405. //
  406. // line status
  407. //
  408.         case IIR_LINE_STATUS_INTERRUPT :
  409.             line_status = INPUT( uart + LINE_STATUS_REGISTER );
  410.  
  411.             if ( line_status & LSR_OVERRUN_ERROR )
  412.                 ++numOverrunError;
  413.  
  414.             if ( line_status & LSR_PARITY_ERROR )
  415.                 ++numParityError;
  416.  
  417.             if ( line_status & LSR_FRAMING_ERROR )
  418.                 ++numFramingError;
  419.  
  420.             if ( line_status & LSR_BREAK_DETECT )
  421.                 ++numBreak;
  422.  
  423.             break;
  424.  
  425. //
  426. // done
  427. //
  428.         default :
  429. //I_ColorBlack (0,0,0);
  430.             OUTPUT( 0x20, 0x20 );
  431.             return;
  432.         }
  433.     }
  434. }
  435.  
  436. /*
  437. ===============
  438. =
  439. = jump_start
  440. =
  441. = Start up the transmition interrupts by sending the first char
  442. ===============
  443. */
  444.  
  445. void jump_start( void )
  446. {
  447.     int c;
  448.  
  449.     if (outque.size != 0)
  450.     {
  451.       c = outque.data [outque.tail++];
  452.       outque.size--;
  453.       if (outque.tail >= QUESIZE)
  454.          outque.tail = 0;      // wrap around
  455.         OUTPUT( uart, c );
  456.     }
  457. }
  458.  
  459.  
  460.