home *** CD-ROM | disk | FTP | other *** search
/ D!Zone (Collector's Edition) / D_ZONE_CD.ISO / programs / editors / serial28 / source.exe / PORT.C < prev    next >
C/C++ Source or Header  |  1994-03-08  |  8KB  |  424 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. int            uart;            // io address
  17. enum {UART_8250, UART_16550} uart_type;
  18. int            irq;
  19.  
  20. int            modem_status = -1;
  21. int            line_status = -1;
  22.  
  23. void interrupt (*oldirqvect) (void);
  24. int            irqintnum;
  25.  
  26. int               comport;
  27.  
  28. extern unsigned char bauddivl, usehardhand;
  29. extern    int    useextirq;
  30. extern  int useextport;
  31.  
  32. int            accessTX;
  33. int            accessRX;
  34. int            accessIIR;
  35. int            accessLCR;
  36. int            accessMCR;
  37. int            accessLSR;
  38. int            accessMSR;
  39.  
  40. long            intRX;
  41. long            intTX;
  42.  
  43. /*
  44. ==============
  45. =
  46. = GetUart
  47. =
  48. ==============
  49. */
  50.  
  51. void GetUart (void)
  52. {
  53.     char   far *system_data;
  54.     static int ISA_uarts[] = {0x3f8,0x2f8,0x3e8,0x2e8};
  55.     static int ISA_IRQs[] = {4,3,4,3};
  56.     static int MCA_uarts[] = {0x03f8,0x02f8,0x3220,0x3228};
  57.     static int MCA_IRQs[] = {4,3,3,3};
  58.     int        p;
  59.  
  60.     if (CheckParm ("-com2"))
  61.         comport = 2;
  62.     else if (CheckParm ("-com3"))
  63.         comport = 3;
  64.     else if (CheckParm ("-com4"))
  65.         comport = 4;
  66.     else
  67.         comport = 1;
  68.  
  69.     regs.h.ah = 0xc0;
  70.     int86x( 0x15, ®s, ®s, &sregs );
  71.     if ( regs.x.cflag )
  72.     {
  73.         irq = ISA_IRQs[ comport-1 ];
  74.         uart = ISA_uarts[ comport-1 ];
  75.         return;
  76.     }
  77.     system_data = ( char far *) ( ( (long) sregs.es << 16 ) + regs.x.bx );
  78.     if ( system_data[ 5 ] & 0x02 )
  79.     {
  80.         irq = MCA_IRQs[ comport-1 ];
  81.         uart = MCA_uarts[ comport-1 ];
  82.     }
  83.     else
  84.     {
  85.         irq = ISA_IRQs[ comport-1 ];
  86.         uart = ISA_uarts[ comport-1 ];
  87.     }
  88.  
  89.     p = CheckParm ("-port");
  90.     if (p)
  91.         scanf (_argv[p+1],"0x%x",&uart);
  92.     p = CheckParm ("-irq");
  93.     if (p)
  94.         scanf (_argv[p+1],"%i",&irq);
  95.     if (useextirq)
  96.         irq=useextirq;
  97.     if (useextport)
  98.         uart=useextport;
  99.  
  100.     printf ("Looking for UART at port 0x%x, irq %i\n",uart,irq);
  101. }
  102.  
  103.  
  104.  
  105.  
  106. /*
  107. ===============
  108. =
  109. = InitPort
  110. =
  111. ===============
  112. */
  113.  
  114. void InitPort (void)
  115. {
  116.     int mcr;
  117.     int    temp;
  118.  
  119. //
  120. // find the irq and io address of the port
  121. //
  122.     GetUart ();
  123.  
  124.     accessTX=uart+TRANSMIT_HOLDING_REGISTER;
  125.     accessRX=uart+RECEIVE_BUFFER_REGISTER;
  126.     accessIIR=uart+INTERRUPT_ID_REGISTER;
  127.     accessLCR=uart+LINE_CONTROL_REGISTER;
  128.     accessMCR=uart+MODEM_CONTROL_REGISTER;
  129.     accessLSR=uart+LINE_STATUS_REGISTER;
  130.     accessMSR=uart+MODEM_STATUS_REGISTER;
  131.  
  132.  
  133. //
  134. // init com port settings
  135. //
  136.     regs.x.ax = 0xf3;        //f3= 9600 n 8 1
  137.     regs.x.dx = comport - 1;
  138.     int86 (0x14, ®s, ®s);
  139.  
  140. //  Tony's add ons.
  141. //  We should be setting the baud rate to 38400 and raising DTR
  142. // set speed to 38400
  143.     OUTPUT(uart + LINE_CONTROL_REGISTER,
  144.                     INPUT(uart + LINE_CONTROL_REGISTER)|LCR_DLAB);
  145.     OUTPUT(uart + DIVISOR_LATCH_LOW,bauddivl);
  146.     OUTPUT(uart + DIVISOR_LATCH_HIGH,0x00);
  147.     OUTPUT(uart + LINE_CONTROL_REGISTER,
  148.                     INPUT(uart + LINE_CONTROL_REGISTER)&~LCR_DLAB);
  149.     OUTPUT(uart + LINE_CONTROL_REGISTER,0x03);   //set 8N1
  150. // set DTR & RTS
  151.     OUTPUT(uart + MODEM_CONTROL_REGISTER,
  152.                     INPUT(uart + MODEM_CONTROL_REGISTER) | MCR_DTR | MCR_RTS);
  153.  
  154.  
  155. //
  156. // check for a 16550
  157. //
  158.     OUTPUT( uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE + FCR_TRIGGER_14 );
  159.     temp = INPUT( uart + INTERRUPT_ID_REGISTER );
  160.     if ( ( temp & 0xf8 ) == 0xc0 )
  161.     {
  162.         uart_type = UART_16550;
  163.         printf ("UART is a 16550\n\n");
  164.     }
  165.     else
  166.     {
  167.         uart_type = UART_8250;
  168.         OUTPUT( uart + FIFO_CONTROL_REGISTER, 0 );
  169.         printf ("UART is an 8250\n\n");
  170.     }
  171.  
  172. //
  173. // prepare for interrupts
  174. //
  175.     outque.head=0;
  176.     outque.tail=0;
  177.     inque.head=0;
  178.     inque.tail=0;
  179.     intTX=0;
  180.     intRX=0;
  181.  
  182.     OUTPUT( uart + INTERRUPT_ENABLE_REGISTER, 0 );
  183.     mcr = INPUT( uart + MODEM_CONTROL_REGISTER );
  184.     mcr |= MCR_OUT2;
  185.     mcr &= ~MCR_LOOPBACK;
  186.     OUTPUT( uart + MODEM_CONTROL_REGISTER, mcr );
  187.  
  188.     INPUT( uart );  // Clear any pending interrupts
  189.     INPUT( uart + INTERRUPT_ID_REGISTER );
  190.  
  191. //
  192. // hook the irq vector
  193. //
  194.     irqintnum = irq + 8;
  195.  
  196.     oldirqvect = getvect (irqintnum);
  197.     if (uart_type == UART_16550)
  198.         setvect (irqintnum,isr_16550);
  199.     else
  200.         setvect (irqintnum,isr_8250);
  201.  
  202.     OUTPUT( 0x20 + 1, INPUT( 0x20 + 1 ) & ~(1<<irq) );
  203.  
  204.     CLI();
  205.  
  206. // enable RX and TX interrupts at the uart
  207.  
  208.     OUTPUT( uart + INTERRUPT_ENABLE_REGISTER,
  209.             IER_RX_DATA_READY + IER_TX_HOLDING_REGISTER_EMPTY);
  210.  
  211. // enable interrupts through the interrupt controller
  212.  
  213.     OUTPUT( 0x20, 0xc2 );
  214.  
  215. // set DTR
  216.     OUTPUT( uart + MODEM_CONTROL_REGISTER
  217.         , INPUT( uart + MODEM_CONTROL_REGISTER ) | MCR_DTR);
  218.  
  219.  
  220.     STI();
  221.  
  222.  
  223. }
  224.  
  225.  
  226. /*
  227. =============
  228. =
  229. = ShutdownPort
  230. =
  231. =============
  232. */
  233.  
  234. void ShutdownPort ( void )
  235. {
  236.     OUTPUT( uart + INTERRUPT_ENABLE_REGISTER, 0 );
  237.     OUTPUT( uart + MODEM_CONTROL_REGISTER, 0 );
  238.  
  239.     OUTPUT( 0x20 + 1, INPUT( 0x20 + 1 ) | (1<<irq) );
  240.     OUTPUT( uart + FIFO_CONTROL_REGISTER, 0 );
  241.  
  242.     setvect (irqintnum,oldirqvect);
  243.  
  244. //
  245. // init com port settings to defaults
  246. //
  247.     regs.x.ax = 0xf3;        //f3= 9600 n 8 1
  248.     regs.x.dx = comport - 1;
  249.     int86 (0x14, ®s, ®s);
  250. }
  251.  
  252.  
  253. int read_byte( void )
  254. {
  255.     int    c;
  256.  
  257.     // Tony's code again, raise RTS if buffer half empty
  258.     if ((inque.head-inque.tail)<(QUESIZE/2))
  259.         OUTPUT( accessMCR,INPUT(accessMCR) | MCR_RTS);
  260.  
  261.     if (inque.tail >= inque.head)
  262.         return -1;
  263.     c = inque.data[inque.tail&(QUESIZE-1)];
  264.     inque.tail++;
  265.     return c;
  266. }
  267.  
  268.  
  269. void write_byte( int c )
  270. {
  271.     outque.data[outque.head&(QUESIZE-1)] = c;
  272.     outque.head++;
  273. }
  274.  
  275.  
  276.  
  277. //==========================================================================
  278.  
  279.  
  280. /*
  281. ==============
  282. =
  283. = isr_16550
  284. =
  285. ==============
  286. */
  287.  
  288. void interrupt isr_16550(void)
  289. {
  290.     int    count;
  291.  
  292.     while (1)
  293.     {
  294.         switch( INPUT( accessIIR ) & 7 )
  295.         {
  296. //
  297. // receive
  298. //
  299.         case IIR_RX_DATA_READY_INTERRUPT :
  300. //I_ColorBlack (0,63,0);
  301.             intRX++;
  302.             do
  303.             {
  304.                 inque.data[(inque.head++)&(QUESIZE-1)] = INPUT(accessRX);
  305.             }
  306.             while (INPUT(accessLSR) & LSR_DATA_READY );
  307.             if (((outque.head-outque.tail)>(QUESIZE-1000))&&usehardhand)
  308.                     OUTPUT(accessMCR,INPUT(accessMCR) & ~MCR_RTS);
  309.  
  310.             break;
  311.  
  312. //
  313. // transmit
  314. //
  315.         case IIR_TX_HOLDING_REGISTER_INTERRUPT :
  316. //I_ColorBlack (63,0,0);
  317.             if ((outque.tail < outque.head)&&
  318.                     ((INPUT(accessMSR)&MSR_CTS)||!usehardhand))
  319.             {
  320.                 intTX++;
  321.                 count = 16;
  322.                 do
  323.                 {
  324.                     OUTPUT( accessTX, outque.data[(outque.tail++)&(QUESIZE-1)]);
  325.                 } while (--count && outque.tail < outque.head);
  326.             }
  327.             break;
  328.  
  329. // not enabled
  330.         case IIR_MODEM_STATUS_INTERRUPT :
  331.             modem_status = INPUT(accessMSR);
  332.             break;
  333.  
  334. // not enabled
  335.         case IIR_LINE_STATUS_INTERRUPT :
  336.             line_status = INPUT( accessLSR );
  337.             break;
  338.  
  339. //
  340. // done
  341. //
  342.         default :
  343.             OUTPUT( 0x20, 0x20 );
  344.             return;
  345.         }
  346.     }
  347. }
  348.  
  349. void interrupt isr_8250(void)
  350. {
  351.  
  352.     while (1)
  353.     {
  354.         switch( INPUT(accessIIR) & 7 )
  355.         {
  356. //
  357. // receive
  358. //
  359.         case IIR_RX_DATA_READY_INTERRUPT :
  360.  
  361.             intRX++;
  362.             inque.data[inque.head++&(QUESIZE-1)] = INPUT(accessRX);
  363.  
  364.             if (((outque.head-outque.tail)>(QUESIZE-1000))&&usehardhand)
  365.                     OUTPUT(accessMCR,INPUT(accessMCR) & ~MCR_RTS);
  366.  
  367.             break;
  368.  
  369. //
  370. // transmit
  371. //
  372.         case IIR_TX_HOLDING_REGISTER_INTERRUPT :
  373.             if ((outque.tail < outque.head)&&
  374.                     ((INPUT(accessMSR)&MSR_CTS)||!usehardhand))
  375.             {
  376.                 intTX++;
  377.                 OUTPUT( accessTX, outque.data[(outque.tail++)&(QUESIZE-1)]);
  378.             }
  379.             break;
  380.  
  381. // not enabled
  382.         case IIR_MODEM_STATUS_INTERRUPT :
  383.             modem_status = INPUT( accessMSR );
  384.             break;
  385.  
  386. // not enabled
  387.         case IIR_LINE_STATUS_INTERRUPT :
  388.             line_status = INPUT( accessLSR );
  389.             break;
  390.  
  391. //
  392. // done
  393. //
  394.         default :
  395.             OUTPUT( 0x20, 0x20 );
  396.             return;
  397.         }
  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.tail < outque.head)
  416.     {
  417.         c = outque.data [outque.tail&(QUESIZE-1)];
  418.         outque.tail++;
  419.         OUTPUT( uart, c );
  420.     }
  421. }
  422.  
  423.  
  424.