home *** CD-ROM | disk | FTP | other *** search
/ 1,001 Nights of Doom / 1001NightsOfDoom1995wickedSensations.iso / modem / ser6_src.zip / PORT.C < prev    next >
C/C++ Source or Header  |  1994-11-16  |  9KB  |  424 lines

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