// port.c #include "doomnet.h" #include "sersetup.h" void jump_start( void ); void interrupt isr_8250 (void); union REGS regs; struct SREGS sregs; que_t inque, outque; int uart; // io address enum {UART_8250, UART_16550} uart_type; int irq; int modem_status = -1; int line_status = -1; void interrupt (*oldirqvect) (void); int irqintnum; int comport; /* ============== = = GetUart = ============== */ void GetUart (void) { char far *system_data; static int ISA_uarts[] = {0x3f8,0x2f8,0x3e8,0x2e8}; static int ISA_IRQs[] = {4,3,4,3}; static int MCA_uarts[] = {0x03f8,0x02f8,0x3220,0x3228}; static int MCA_IRQs[] = {4,3,3,3}; int p; if (CheckParm ("-com2")) comport = 2; else if (CheckParm ("-com3")) comport = 3; else if (CheckParm ("-com4")) comport = 4; else comport = 1; regs.h.ah = 0xc0; int86x( 0x15, ®s, ®s, &sregs ); if ( regs.x.cflag ) { irq = ISA_IRQs[ comport-1 ]; uart = ISA_uarts[ comport-1 ]; return; } system_data = ( char far *) ( ( (long) sregs.es << 16 ) + regs.x.bx ); if ( system_data[ 5 ] & 0x02 ) { irq = MCA_IRQs[ comport-1 ]; uart = MCA_uarts[ comport-1 ]; } else { irq = ISA_IRQs[ comport-1 ]; uart = ISA_uarts[ comport-1 ]; } p = CheckParm ("-port"); if (p) scanf (_argv[p+1],"0x%x",&uart); p = CheckParm ("-irq"); if (p) scanf (_argv[p+1],"%i",&irq); printf ("Looking for UART at port 0x%x, irq %i\n",uart,irq); } /* =============== = = InitPort = =============== */ void InitPort (void) { int mcr; int temp; // // find the irq and io address of the port // GetUart (); // // init com port settings // regs.x.ax = 0xf3; //f3= 9600 n 8 1 regs.x.dx = comport - 1; int86 (0x14, ®s, ®s); // // check for a 16550 // OUTPUT( uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE + FCR_TRIGGER_04 ); temp = INPUT( uart + INTERRUPT_ID_REGISTER ); if ( ( temp & 0xf8 ) == 0xc0 ) { uart_type = UART_16550; printf ("UART is a 16550\n\n"); } else { uart_type = UART_8250; OUTPUT( uart + FIFO_CONTROL_REGISTER, 0 ); printf ("UART is an 8250\n\n"); } // // prepare for interrupts // OUTPUT( uart + INTERRUPT_ENABLE_REGISTER, 0 ); mcr = INPUT( uart + MODEM_CONTROL_REGISTER ); mcr |= MCR_OUT2; mcr &= ~MCR_LOOPBACK; OUTPUT( uart + MODEM_CONTROL_REGISTER, mcr ); INPUT( uart ); // Clear any pending interrupts INPUT( uart + INTERRUPT_ID_REGISTER ); // // hook the irq vector // irqintnum = irq + 8; oldirqvect = getvect (irqintnum); setvect (irqintnum,isr_8250); OUTPUT( 0x20 + 1, INPUT( 0x20 + 1 ) & ~(1<= inque.head) return -1; c = inque.data[inque.tail%QUESIZE]; inque.tail++; return c; } void write_byte( int c ) { outque.data[outque.head%QUESIZE] = c; outque.head++; } //========================================================================== /* ============== = = isr_8250 = ============== */ void interrupt isr_8250(void) { int c; int count; while (1) { switch( INPUT( uart + INTERRUPT_ID_REGISTER ) & 7 ) { // not enabled case IIR_MODEM_STATUS_INTERRUPT : modem_status = INPUT( uart + MODEM_STATUS_REGISTER ); break; // not enabled case IIR_LINE_STATUS_INTERRUPT : line_status = INPUT( uart + LINE_STATUS_REGISTER ); break; // // transmit // case IIR_TX_HOLDING_REGISTER_INTERRUPT : //I_ColorBlack (63,0,0); if (outque.tail < outque.head) { if (uart_type == UART_16550) count = 16; else count = 1; do { c = outque.data[outque.tail%QUESIZE]; outque.tail++; OUTPUT( uart + TRANSMIT_HOLDING_REGISTER, c ); } while (--count && outque.tail < outque.head); } break; // // receive // case IIR_RX_DATA_READY_INTERRUPT : //I_ColorBlack (0,63,0); do { c = INPUT( uart + RECEIVE_BUFFER_REGISTER ); inque.data[inque.head%QUESIZE] = c; inque.head++; } while ( uart_type == UART_16550 && INPUT( uart + LINE_STATUS_REGISTER ) & LSR_DATA_READY ); break; // // done // default : //I_ColorBlack (0,0,0); OUTPUT( 0x20, 0x20 ); return; } } } /* =============== = = jump_start = = Start up the transmition interrupts by sending the first char =============== */ void jump_start( void ) { int c; if (outque.tail < outque.head) { c = outque.data [outque.tail%QUESIZE]; outque.tail++; OUTPUT( uart, c ); } }