diff options
| author | wyatt8740 <wyatt8740@yahoo.com> | 2014-01-06 12:02:16 -0500 |
|---|---|---|
| committer | wyatt8740 <wyatt8740@yahoo.com> | 2014-01-06 12:02:16 -0500 |
| commit | a8f828a066773a59fdf646299359d35ae0e845af (patch) | |
| tree | 86123409fc6f231cf4136e81159b63cb1e9ec102 /WinQuake/net_comx.c | |
| parent | b2951690415054ae8705c07f8df7a4ba7cde382a (diff) | |
| download | quake-pum-a8f828a066773a59fdf646299359d35ae0e845af.tar.gz | |
Removed accidental upload of copyrighted map files
Diffstat (limited to 'WinQuake/net_comx.c')
| -rw-r--r-- | WinQuake/net_comx.c | 2570 |
1 files changed, 1285 insertions, 1285 deletions
diff --git a/WinQuake/net_comx.c b/WinQuake/net_comx.c index 2115a14..77793de 100644 --- a/WinQuake/net_comx.c +++ b/WinQuake/net_comx.c @@ -1,1285 +1,1285 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_comx.c - -#include <dos.h> -#include <dpmi.h> - -#define NUM_COM_PORTS 2 - -#define ERR_TTY_LINE_STATUS -1 -#define ERR_TTY_MODEM_STATUS -2 -#define ERR_TTY_NODATA -3 - -#define QUEUESIZE 8192 -#define QUEUEMASK (QUEUESIZE - 1) - -typedef struct -{ - volatile int head; - volatile int tail; - volatile byte data[QUEUESIZE]; -} queue; - -#define FULL(q) (q.head == ((q.tail-1) & QUEUEMASK)) -#define EMPTY(q) (q.tail == q.head) -#define ENQUEUE(q,b) (q.data[q.head] = b, q.head = (q.head + 1) & QUEUEMASK) -#define DEQUEUE(q,b) (b = q.data[q.tail], q.tail = (q.tail + 1) & QUEUEMASK) - -extern cvar_t config_com_port; -extern cvar_t config_com_irq; -extern cvar_t config_com_baud; -extern cvar_t config_com_modem; -extern cvar_t config_modem_dialtype; -extern cvar_t config_modem_clear; -extern cvar_t config_modem_init; -extern cvar_t config_modem_hangup; - -extern int m_return_state; -extern int m_state; -extern qboolean m_return_onerror; -extern char m_return_reason[32]; - -// 8250, 16550 definitions -#define TRANSMIT_HOLDING_REGISTER 0x00 -#define RECEIVE_BUFFER_REGISTER 0x00 -#define INTERRUPT_ENABLE_REGISTER 0x01 -#define IER_RX_DATA_READY 0x01 -#define IER_TX_HOLDING_REGISTER_EMPTY 0x02 -#define IER_LINE_STATUS 0x04 -#define IER_MODEM_STATUS 0x08 -#define INTERRUPT_ID_REGISTER 0x02 -#define IIR_MODEM_STATUS_INTERRUPT 0x00 -#define IIR_TX_HOLDING_REGISTER_INTERRUPT 0x02 -#define IIR_RX_DATA_READY_INTERRUPT 0x04 -#define IIR_LINE_STATUS_INTERRUPT 0x06 -#define IIR_FIFO_TIMEOUT 0x0c -#define IIR_FIFO_ENABLED 0xc0 -#define FIFO_CONTROL_REGISTER 0x02 -#define FCR_FIFO_ENABLE 0x01 -#define FCR_RCVR_FIFO_RESET 0x02 -#define FCR_XMIT_FIFO_RESET 0x04 -#define FCR_TRIGGER_01 0x00 -#define FCR_TRIGGER_04 0x40 -#define FCR_TRIGGER_08 0x80 -#define FCR_TRIGGER_16 0xc0 -#define LINE_CONTROL_REGISTER 0x03 -#define LCR_DATA_BITS_5 0x00 -#define LCR_DATA_BITS_6 0x01 -#define LCR_DATA_BITS_7 0x02 -#define LCR_DATA_BITS_8 0x03 -#define LCR_STOP_BITS_1 0x00 -#define LCR_STOP_BITS_2 0x04 -#define LCR_PARITY_NONE 0x00 -#define LCR_PARITY_ODD 0x08 -#define LCR_PARITY_EVEN 0x18 -#define LCR_PARITY_MARK 0x28 -#define LCR_PARITY_SPACE 0x38 -#define LCR_SET_BREAK 0x40 -#define LCR_DLAB 0x80 -#define MODEM_CONTROL_REGISTER 0x04 -#define MCR_DTR 0x01 -#define MCR_RTS 0x02 -#define MCR_OUT1 0x04 -#define MCR_OUT2 0x08 -#define MCR_LOOPBACK 0x10 -#define LINE_STATUS_REGISTER 0x05 -#define LSR_DATA_READY 0x01 -#define LSR_OVERRUN_ERROR 0x02 -#define LSR_PARITY_ERROR 0x04 -#define LSR_FRAMING_ERROR 0x08 -#define LSR_BREAK_DETECT 0x10 -#define LSR_TRANSMITTER_BUFFER_EMPTY 0x20 -#define LSR_TRANSMITTER_EMPTY 0x40 -#define LSR_FIFO_DIRTY 0x80 -#define MODEM_STATUS_REGISTER 0x06 -#define MSR_DELTA_CTS 0x01 -#define MSR_DELTA_DSR 0x02 -#define MSR_DELTA_RI 0x04 -#define MSR_DELTA_CD 0x08 -#define MSR_CTS 0x10 -#define MSR_DSR 0x20 -#define MSR_RI 0x40 -#define MSR_CD 0x80 -#define DIVISOR_LATCH_LOW 0x00 -#define DIVISOR_LATCH_HIGH 0x01 - -#define MODEM_STATUS_MASK (MSR_CTS | MSR_DSR | MSR_CD) - -#define UART_AUTO 0 -#define UART_8250 1 -#define UART_16550 2 - -static int ISA_uarts[] = {0x3f8,0x2f8,0x3e8,0x2e8}; -static int ISA_IRQs[] = {4,3,4,3}; - -typedef struct ComPort_s -{ - struct ComPort_s *next; - _go32_dpmi_seginfo protectedModeInfo; - _go32_dpmi_seginfo protectedModeSaveInfo; - int uart; - volatile byte modemStatus; - byte modemStatusIgnore; - byte lineStatus; - byte bufferUsed; - qboolean enabled; - volatile qboolean statusUpdated; - qboolean useModem; - qboolean modemInitialized; - qboolean modemRang; - qboolean modemConnected; - queue inputQueue; - queue outputQueue; - char clear[16]; - char startup[32]; - char shutdown[16]; - char buffer[128]; - PollProcedure poll; - double timestamp; - byte uartType; - byte irq; - byte baudBits; - byte lineControl; - byte portNumber; - char dialType; - char name[4]; -} ComPort; - -ComPort *portList = NULL; -ComPort *handleToPort [NUM_COM_PORTS]; - -static int Modem_Command(ComPort *p, char *commandString); -static char *Modem_Response(ComPort *p); -static void Modem_Hangup(ComPort *p); - -int TTY_Init(void); -void TTY_Shutdown(void); -int TTY_Open(int serialPortNumber); -void TTY_Close(int handle); -int TTY_ReadByte(int handle); -int TTY_WriteByte(int handle, byte data); -void TTY_Flush(int handle); -int TTY_Connect(int handle, char *host); -void TTY_Disconnect(int handle); -qboolean TTY_CheckForConnection(int handle); -qboolean TTY_IsEnabled(int serialPortNumber); -qboolean TTY_IsModem(int serialPortNumber); -qboolean TTY_OutputQueueIsEmpty(int handle); - -static void ISR_8250 (ComPort *p) -{ - byte source = 0; - byte b; - - disable(); - - while((source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07) != 1) - { - switch (source) - { - case IIR_RX_DATA_READY_INTERRUPT: - b = inportb (p->uart + RECEIVE_BUFFER_REGISTER); - if (! FULL(p->inputQueue)) - { - ENQUEUE (p->inputQueue, b); - } - else - { - p->lineStatus |= LSR_OVERRUN_ERROR; - p->statusUpdated = true; - } - break; - - case IIR_TX_HOLDING_REGISTER_INTERRUPT: - if (! EMPTY(p->outputQueue)) - { - DEQUEUE (p->outputQueue, b); - outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b); - } - break; - - case IIR_MODEM_STATUS_INTERRUPT: - p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; - p->statusUpdated = true; - break; - - case IIR_LINE_STATUS_INTERRUPT: - p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER); - p->statusUpdated = true; - break; - } - source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07; - } - outportb (0x20, 0x20); -} - -static void COM1_ISR_8250 (void) -{ - ISR_8250 (handleToPort[0]); -} - -static void COM2_ISR_8250 (void) -{ - ISR_8250 (handleToPort[1]); -} - - - -static void ISR_16550 (ComPort *p) -{ - int count; - byte source; - byte b; - - disable(); - while((source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07) != 1) - { - switch (source) - { - case IIR_RX_DATA_READY_INTERRUPT: - do - { - b = inportb (p->uart + RECEIVE_BUFFER_REGISTER); - if (!FULL(p->inputQueue)) - { - ENQUEUE (p->inputQueue, b); - } - else - { - p->lineStatus |= LSR_OVERRUN_ERROR; - p->statusUpdated = true; - } - } while (inportb (p->uart + LINE_STATUS_REGISTER) & LSR_DATA_READY); - break; - - case IIR_TX_HOLDING_REGISTER_INTERRUPT: - count = 16; - while ((! EMPTY(p->outputQueue)) && count--) - { - DEQUEUE (p->outputQueue, b); - outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b); - } - break; - - case IIR_MODEM_STATUS_INTERRUPT: - p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; - p->statusUpdated = true; - break; - - case IIR_LINE_STATUS_INTERRUPT: - p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER); - p->statusUpdated = true; - break; - } - source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07; - } - - // check for lost IIR_TX_HOLDING_REGISTER_INTERRUPT on 16550a! - if (inportb (p->uart + LINE_STATUS_REGISTER ) & LSR_TRANSMITTER_EMPTY) - { - count = 16; - while ((! EMPTY(p->outputQueue)) && count--) - { - DEQUEUE (p->outputQueue, b); - outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b); - } - } - - outportb (0x20, 0x20); -} - -static void COM1_ISR_16550 (void) -{ - ISR_16550 (handleToPort[0]); -} - -static void COM2_ISR_16550 (void) -{ - ISR_16550 (handleToPort[1]); -} - - -void TTY_GetComPortConfig (int portNumber, int *port, int *irq, int *baud, qboolean *useModem) -{ - ComPort *p; - - p = handleToPort[portNumber]; - *port = p->uart; - *irq = p->irq; - *baud = 115200 / p->baudBits; - *useModem = p->useModem; -} - -void TTY_SetComPortConfig (int portNumber, int port, int irq, int baud, qboolean useModem) -{ - ComPort *p; - float temp; - - if (useModem) - { - if (baud == 14400) - baud = 19200; - if (baud == 28800) - baud = 38400; - } - - p = handleToPort[portNumber]; - p->uart = port; - p->irq = irq; - p->baudBits = 115200 / baud; - p->useModem = useModem; - - if (useModem) - temp = 1.0; - else - temp = 0.0; - - Cvar_SetValue ("_config_com_port", (float)port); - Cvar_SetValue ("_config_com_irq", (float)irq); - Cvar_SetValue ("_config_com_baud", (float)baud); - Cvar_SetValue ("_config_com_modem", temp); -} - -void TTY_GetModemConfig (int portNumber, char *dialType, char *clear, char *init, char *hangup) -{ - ComPort *p; - - p = handleToPort[portNumber]; - *dialType = p->dialType; - Q_strcpy(clear, p->clear); - Q_strcpy(init, p->startup); - Q_strcpy(hangup, p->shutdown); -} - -void TTY_SetModemConfig (int portNumber, char *dialType, char *clear, char *init, char *hangup) -{ - ComPort *p; - - p = handleToPort[portNumber]; - p->dialType = dialType[0]; - Q_strcpy(p->clear, clear); - Q_strcpy(p->startup, init); - Q_strcpy(p->shutdown, hangup); - - p->modemInitialized = false; - - Cvar_Set ("_config_modem_dialtype", dialType); - Cvar_Set ("_config_modem_clear", clear); - Cvar_Set ("_config_modem_init", init); - Cvar_Set ("_config_modem_hangup", hangup); -} - - -static void ResetComPortConfig (ComPort *p) -{ - p->useModem = false; - p->uartType = UART_AUTO; - p->uart = ISA_uarts[p->portNumber]; - p->irq = ISA_IRQs[p->portNumber]; - p->modemStatusIgnore = MSR_CD | MSR_CTS | MSR_DSR; - p->baudBits = 115200 / 57600; - p->lineControl = LCR_DATA_BITS_8 | LCR_STOP_BITS_1 | LCR_PARITY_NONE; - Q_strcpy(p->clear, "ATZ"); - Q_strcpy(p->startup, ""); - Q_strcpy(p->shutdown, "AT H"); - p->modemRang = false; - p->modemConnected = false; - p->statusUpdated = false; - p->outputQueue.head = p->outputQueue.tail = 0; - p->inputQueue.head = p->inputQueue.tail = 0; -} - - -static void ComPort_Enable(ComPort *p) -{ - void (*isr)(void); - int n; - byte b; - - if (p->enabled) - { - Con_Printf("Already enabled\n"); - return; - } - - // disable all UART interrupts - outportb (p->uart + INTERRUPT_ENABLE_REGISTER, 0); - - // clear out any buffered uncoming data - while((inportb (p->uart + LINE_STATUS_REGISTER)) & LSR_DATA_READY) - inportb (p->uart + RECEIVE_BUFFER_REGISTER); - - // get the current line and modem status - p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; - p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER); - - // clear any UART interrupts - do - { - n = inportb (p->uart + INTERRUPT_ID_REGISTER) & 7; - if (n == IIR_RX_DATA_READY_INTERRUPT) - inportb (p->uart + RECEIVE_BUFFER_REGISTER); - } while (!(n & 1)); - - if (p->uartType == UART_AUTO) - { - outportb (p->uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE); - b = inportb (p->uart + INTERRUPT_ID_REGISTER); - if ((b & IIR_FIFO_ENABLED) == IIR_FIFO_ENABLED) - p->uartType = UART_16550; - else - p->uartType = UART_8250; - } - - // save the old interrupt handler - _go32_dpmi_get_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeSaveInfo); - - if (p->uartType == UART_8250) - { - outportb (p->uart + FIFO_CONTROL_REGISTER, 0); - if (p == handleToPort[0]) - isr = COM1_ISR_8250; - else - isr = COM2_ISR_8250; - } - else - { - outportb (p->uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE | FCR_RCVR_FIFO_RESET | FCR_XMIT_FIFO_RESET | FCR_TRIGGER_08); - if (p == handleToPort[0]) - isr = COM1_ISR_16550; - else - isr = COM2_ISR_16550; - } - - p->protectedModeInfo.pm_offset = (int)isr; - - n = _go32_dpmi_allocate_iret_wrapper(&p->protectedModeInfo); - if (n) - { - Con_Printf("serial: protected mode callback allocation failed\n"); - return; - } - - // disable interrupts at the processor - disable(); - - // install our interrupt handlers now - _go32_dpmi_set_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeInfo); - - // enable our interrupt at the PIC - outportb (0x21, inportb (0x21) & ~(1<<p->irq)); - - // enable interrupts at the processor - enable(); - - // enable interrupts at the PIC - outportb (0x20, 0xc2); - - // set baud rate & line control - outportb (p->uart + LINE_CONTROL_REGISTER, LCR_DLAB | p->lineControl); - outportb (p->uart, p->baudBits); - outportb (p->uart + 1, 0); - outportb (p->uart + LINE_CONTROL_REGISTER, p->lineControl); - - // set modem control register & enable uart interrupt generation - outportb(p->uart + MODEM_CONTROL_REGISTER, MCR_OUT2 | MCR_RTS | MCR_DTR); - - // enable the individual interrupts at the uart - outportb (p->uart + INTERRUPT_ENABLE_REGISTER, IER_RX_DATA_READY | IER_TX_HOLDING_REGISTER_EMPTY | IER_LINE_STATUS | IER_MODEM_STATUS); - - p->enabled = true; -} - - -static void ComPort_Disable(ComPort *p) -{ - if (!p->enabled) - { - Con_Printf("Already disabled\n"); - return; - } - - // disable interrupts at the uart - outportb (p->uart + INTERRUPT_ENABLE_REGISTER, 0); - - // disable our interrupt at the PIC - outportb (0x21, inportb (0x21) | (1<<p->irq)); - - // disable interrupts at the processor - disable(); - - // restore the old interrupt handler - _go32_dpmi_set_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeSaveInfo); - _go32_dpmi_free_iret_wrapper(&p->protectedModeInfo); - - // enable interrupts at the processor - enable(); - - p->enabled = false; -} - - -static int CheckStatus (ComPort *p) -{ - int ret = 0; - - if (p->statusUpdated) - { - p->statusUpdated = false; - - if (p->lineStatus & (LSR_OVERRUN_ERROR | LSR_PARITY_ERROR | LSR_FRAMING_ERROR | LSR_BREAK_DETECT)) - { - if (p->lineStatus & LSR_OVERRUN_ERROR) - Con_DPrintf ("Serial overrun error\n"); - if (p->lineStatus & LSR_PARITY_ERROR) - Con_DPrintf ("Serial parity error\n"); - if (p->lineStatus & LSR_FRAMING_ERROR) - Con_DPrintf ("Serial framing error\n"); - if (p->lineStatus & LSR_BREAK_DETECT) - Con_DPrintf ("Serial break detect\n"); - ret = ERR_TTY_LINE_STATUS; - } - - if ((p->modemStatus & MODEM_STATUS_MASK) != MODEM_STATUS_MASK) - { - if (!(p->modemStatus & MSR_CTS)) - Con_Printf ("Serial lost CTS\n"); - if (!(p->modemStatus & MSR_DSR)) - Con_Printf ("Serial lost DSR\n"); - if (!(p->modemStatus & MSR_CD)) - Con_Printf ("Serial lost Carrier\n"); - ret = ERR_TTY_MODEM_STATUS; - } - } - - return ret; -} - - -static void Modem_Init(ComPort *p) -{ - double start; - char *response; - - Con_Printf ("Initializing modem...\n"); - - // write 0 to MCR, wait 1/2 sec, then write the real value back again - // I got this from the guys at head-to-head who say it's necessary. - outportb(p->uart + MODEM_CONTROL_REGISTER, 0); - start = Sys_FloatTime(); - while ((Sys_FloatTime() - start) < 0.5) - ; - outportb(p->uart + MODEM_CONTROL_REGISTER, MCR_OUT2 | MCR_RTS | MCR_DTR); - start = Sys_FloatTime(); - while ((Sys_FloatTime() - start) < 0.25) - ; - - if (*p->clear) - { - Modem_Command (p, p->clear); - start = Sys_FloatTime(); - while(1) - { - if ((Sys_FloatTime() - start) > 3.0) - { - Con_Printf("No response - clear failed\n"); - p->enabled = false; - goto failed; - } - response = Modem_Response(p); - if (!response) - continue; - if (Q_strncmp(response, "OK", 2) == 0) - break; - if (Q_strncmp(response, "ERROR", 5) == 0) - { - p->enabled = false; - goto failed; - } - } - } - - if (*p->startup) - { - Modem_Command (p, p->startup); - start = Sys_FloatTime(); - while(1) - { - if ((Sys_FloatTime() - start) > 3.0) - { - Con_Printf("No response - init failed\n"); - p->enabled = false; - goto failed; - } - response = Modem_Response(p); - if (!response) - continue; - if (Q_strncmp(response, "OK", 2) == 0) - break; - if (Q_strncmp(response, "ERROR", 5) == 0) - { - p->enabled = false; - goto failed; - } - } - } - - p->modemInitialized = true; - return; - -failed: - if (m_return_onerror) - { - key_dest = key_menu; - m_state = m_return_state; - m_return_onerror = false; - Q_strcpy(m_return_reason, "Initialization Failed"); - } - return; -} - - -void TTY_Enable(int handle) -{ - ComPort *p; - - p = handleToPort [handle]; - if (p->enabled) - return; - - ComPort_Enable(p); - - if (p->useModem && !p->modemInitialized) - Modem_Init (p); -} - - -int TTY_Open(int serialPortNumber) -{ - return serialPortNumber; -} - - -void TTY_Close(int handle) -{ - ComPort *p; - double startTime; - - p = handleToPort [handle]; - - startTime = Sys_FloatTime(); - while ((Sys_FloatTime() - startTime) < 1.0) - if (EMPTY(p->outputQueue)) - break; - - if (p->useModem) - { - if (p->modemConnected) - Modem_Hangup(p); - } -} - - -int TTY_ReadByte(int handle) -{ - int ret; - ComPort *p; - - p = handleToPort [handle]; - - if ((ret = CheckStatus (p)) != 0) - return ret; - - if (EMPTY (p->inputQueue)) - return ERR_TTY_NODATA; - - DEQUEUE (p->inputQueue, ret); - return (ret & 0xff); -} - - -int TTY_WriteByte(int handle, byte data) -{ - ComPort *p; - - p = handleToPort [handle]; - if (FULL(p->outputQueue)) - return -1; - - ENQUEUE (p->outputQueue, data); - return 0; -} - - -void TTY_Flush(int handle) -{ - byte b; - ComPort *p; - - p = handleToPort [handle]; - - if (inportb (p->uart + LINE_STATUS_REGISTER ) & LSR_TRANSMITTER_EMPTY) - { - DEQUEUE (p->outputQueue, b); - outportb(p->uart, b); - } -} - - -int TTY_Connect(int handle, char *host) -{ - double start; - ComPort *p; - char *response = NULL; - keydest_t save_key_dest; - byte dialstring[64]; - byte b; - - p = handleToPort[handle]; - - if ((p->modemStatus & MODEM_STATUS_MASK) != MODEM_STATUS_MASK) - { - Con_Printf ("Serial: line not ready ("); - if ((p->modemStatus & MSR_CTS) == 0) - Con_Printf(" CTS"); - if ((p->modemStatus & MSR_DSR) == 0) - Con_Printf(" DSR"); - if ((p->modemStatus & MSR_CD) == 0) - Con_Printf(" CD"); - Con_Printf(" )"); - return -1; - } - - // discard any scraps in the input buffer - while (! EMPTY (p->inputQueue)) - DEQUEUE (p->inputQueue, b); - - CheckStatus (p); - - if (p->useModem) - { - save_key_dest = key_dest; - key_dest = key_console; - key_count = -2; - - Con_Printf ("Dialing...\n"); - sprintf(dialstring, "AT D%c %s\r", p->dialType, host); - Modem_Command (p, dialstring); - start = Sys_FloatTime(); - while(1) - { - if ((Sys_FloatTime() - start) > 60.0) - { - Con_Printf("Dialing failure!\n"); - break; - } - - Sys_SendKeyEvents (); - if (key_count == 0) - { - if (key_lastpress != K_ESCAPE) - { - key_count = -2; - continue; - } - Con_Printf("Aborting...\n"); - while ((Sys_FloatTime() - start) < 5.0) - ; - disable(); - p->outputQueue.head = p->outputQueue.tail = 0; - p->inputQueue.head = p->inputQueue.tail = 0; - outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) & ~MCR_DTR); - enable(); - start = Sys_FloatTime(); - while ((Sys_FloatTime() - start) < 0.75) - ; - outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) | MCR_DTR); - response = "Aborted"; - break; - } - - response = Modem_Response(p); - if (!response) - continue; - if (Q_strncmp(response, "CONNECT", 7) == 0) - { - disable(); - p->modemRang = true; - p->modemConnected = true; - p->outputQueue.head = p->outputQueue.tail = 0; - p->inputQueue.head = p->inputQueue.tail = 0; - enable(); - key_dest = save_key_dest; - key_count = 0; - m_return_onerror = false; - return 0; - } - if (Q_strncmp(response, "NO CARRIER", 10) == 0) - break; - if (Q_strncmp(response, "NO DIALTONE", 11) == 0) - break; - if (Q_strncmp(response, "NO DIAL TONE", 12) == 0) - break; - if (Q_strncmp(response, "NO ANSWER", 9) == 0) - break; - if (Q_strncmp(response, "BUSY", 4) == 0) - break; - if (Q_strncmp(response, "ERROR", 5) == 0) - break; - } - key_dest = save_key_dest; - key_count = 0; - if (m_return_onerror) - { - key_dest = key_menu; - m_state = m_return_state; - m_return_onerror = false; - Q_strncpy(m_return_reason, response, 31); - } - return -1; - } - m_return_onerror = false; - return 0; -} - - -void TTY_Disconnect(int handle) -{ - ComPort *p; - - p = handleToPort[handle]; - - if (p->useModem && p->modemConnected) - Modem_Hangup(p); -} - - -qboolean TTY_CheckForConnection(int handle) -{ - ComPort *p; - - p = handleToPort[handle]; - - CheckStatus (p); - - if (p->useModem) - { - if (!p->modemRang) - { - if (!Modem_Response(p)) - return false; - - if (Q_strncmp(p->buffer, "RING", 4) == 0) - { - Modem_Command (p, "ATA"); - p->modemRang = true; - p->timestamp = net_time; - } - return false; - } - if (!p->modemConnected) - { - if ((net_time - p->timestamp) > 35.0) - { - Con_Printf("Unable to establish modem connection\n"); - p->modemRang = false; - return false; - } - - if (!Modem_Response(p)) - return false; - - if (Q_strncmp (p->buffer, "CONNECT", 7) != 0) - return false; - - disable(); - p->modemConnected = true; - p->outputQueue.head = p->outputQueue.tail = 0; - p->inputQueue.head = p->inputQueue.tail = 0; - enable(); - Con_Printf("Modem Connect\n"); - return true; - } - return true; - } - - // direct connect case - if (EMPTY (p->inputQueue)) - return false; - return true; -} - - -qboolean TTY_IsEnabled(int serialPortNumber) -{ - return handleToPort[serialPortNumber]->enabled; -} - - -qboolean TTY_IsModem(int serialPortNumber) -{ - return handleToPort[serialPortNumber]->useModem; -} - - -qboolean TTY_OutputQueueIsEmpty(int handle) -{ - return EMPTY(handleToPort[handle]->outputQueue); -} - - -void Com_f (void) -{ - ComPort *p; - int portNumber; - int i; - int n; - - // first, determine which port they're messing with - portNumber = Q_atoi(Cmd_Argv (0) + 3) - 1; - if (portNumber > 1) - return; - p = handleToPort[portNumber]; - - if (Cmd_Argc() == 1) - { - Con_Printf("Settings for COM%i\n", portNumber + 1); - Con_Printf("enabled: %s\n", p->enabled ? "true" : "false"); - Con_Printf("uart: "); - if (p->uartType == UART_AUTO) - Con_Printf("auto\n"); - else if (p->uartType == UART_8250) - Con_Printf("8250\n"); - else - Con_Printf("16550\n"); - Con_Printf("port: %x\n", p->uart); - Con_Printf("irq: %i\n", p->irq); - Con_Printf("baud: %i\n", 115200 / p->baudBits); - Con_Printf("CTS: %s\n", (p->modemStatusIgnore & MSR_CTS) ? "ignored" : "honored"); - Con_Printf("DSR: %s\n", (p->modemStatusIgnore & MSR_DSR) ? "ignored" : "honored"); - Con_Printf("CD: %s\n", (p->modemStatusIgnore & MSR_CD) ? "ignored" : "honored"); - if (p->useModem) - { - Con_Printf("type: Modem\n"); - Con_Printf("clear: %s\n", p->clear); - Con_Printf("startup: %s\n", p->startup); - Con_Printf("shutdown: %s\n", p->shutdown); - } - else - Con_Printf("type: Direct connect\n"); - - return; - } - - - if (Cmd_CheckParm ("disable")) - { - if (p->enabled) - ComPort_Disable(p); - p->modemInitialized = false; - return; - } - - if (Cmd_CheckParm ("reset")) - { - ComPort_Disable(p); - ResetComPortConfig (p); - return; - } - - if ((i = Cmd_CheckParm ("port")) != 0) - { - if (p->enabled) - { - Con_Printf("COM port must be disabled to change port\n"); - return; - } - p->uart = Q_atoi (Cmd_Argv (i+1)); - } - - if ((i = Cmd_CheckParm ("irq")) != 0) - { - if (p->enabled) - { - Con_Printf("COM port must be disabled to change irq\n"); - return; - } - p->irq = Q_atoi (Cmd_Argv (i+1)); - } - - if ((i = Cmd_CheckParm ("baud")) != 0) - { - if (p->enabled) - { - Con_Printf("COM port must be disabled to change baud\n"); - return; - } - n = Q_atoi (Cmd_Argv (i+1)); - if (n == 0) - Con_Printf("Invalid baud rate specified\n"); - else - p->baudBits = 115200 / n; - } - - if (Cmd_CheckParm ("8250")) - { - if (p->enabled) - { - Con_Printf("COM port must be disabled to change uart\n"); - return; - } - p->uartType = UART_8250; - } - if (Cmd_CheckParm ("16550")) - { - if (p->enabled) - { - Con_Printf("COM port must be disabled to change uart\n"); - return; - } - p->uartType = UART_16550; - } - if (Cmd_CheckParm ("auto")) - { - if (p->enabled) - { - Con_Printf("COM port must be disabled to change uart\n"); - return; - } - p->uartType = UART_AUTO; - } - - if (Cmd_CheckParm ("pulse")) - p->dialType = 'P'; - if (Cmd_CheckParm ("tone")) - p->dialType = 'T'; - - if (Cmd_CheckParm ("direct")) - p->useModem = false; - if (Cmd_CheckParm ("modem")) - p->useModem = true; - - if ((i = Cmd_CheckParm ("clear")) != 0) - { - Q_strncpy (p->clear, Cmd_Argv (i+1), 16); - } - - if ((i = Cmd_CheckParm ("startup")) != 0) - { - Q_strncpy (p->startup, Cmd_Argv (i+1), 32); - p->modemInitialized = false; - } - - if ((i = Cmd_CheckParm ("shutdown")) != 0) - { - Q_strncpy (p->shutdown, Cmd_Argv (i+1), 16); - } - - if (Cmd_CheckParm ("-cts")) - { - p->modemStatusIgnore |= MSR_CTS; - p->modemStatus |= MSR_CTS; - } - - if (Cmd_CheckParm ("+cts")) - { - p->modemStatusIgnore &= (~MSR_CTS); - p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; - } - - if (Cmd_CheckParm ("-dsr")) - { - p->modemStatusIgnore |= MSR_DSR; - p->modemStatus |= MSR_DSR; - } - - if (Cmd_CheckParm ("+dsr")) - { - p->modemStatusIgnore &= (~MSR_DSR); - p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; - } - - if (Cmd_CheckParm ("-cd")) - { - p->modemStatusIgnore |= MSR_CD; - p->modemStatus |= MSR_CD; - } - - if (Cmd_CheckParm ("+cd")) - { - p->modemStatusIgnore &= (~MSR_CD); - p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; - } - - if (Cmd_CheckParm ("enable")) - { - if (!p->enabled) - ComPort_Enable(p); - if (p->useModem && !p->modemInitialized) - Modem_Init (p); - } -} - - -int TTY_Init(void) -{ - int n; - ComPort *p; - - for (n = 0; n < NUM_COM_PORTS; n++) - { - p = (ComPort *)Hunk_AllocName(sizeof(ComPort), "comport"); - if (p == NULL) - Sys_Error("Hunk alloc failed for com port\n"); - p->next = portList; - portList = p; - handleToPort[n] = p; - p->portNumber = n; - p->dialType = 'T'; - sprintf(p->name, "com%u", n+1); - Cmd_AddCommand (p->name, Com_f); - ResetComPortConfig (p); - } - - GetComPortConfig = TTY_GetComPortConfig; - SetComPortConfig = TTY_SetComPortConfig; - GetModemConfig = TTY_GetModemConfig; - SetModemConfig = TTY_SetModemConfig; - - return 0; -} - - -void TTY_Shutdown(void) -{ - int n; - ComPort *p; - - for (n = 0; n < NUM_COM_PORTS; n++) - { - p = handleToPort[n]; - if (p->enabled) - { - while (p->modemConnected) - NET_Poll(); - ComPort_Disable (p); - } - } -} - - -static int Modem_Command(ComPort *p, char *commandString) -{ - byte b; - - if (CheckStatus (p)) - return -1; - - disable(); - p->outputQueue.head = p->outputQueue.tail = 0; - p->inputQueue.head = p->inputQueue.tail = 0; - enable(); - p->bufferUsed = 0; - - while (*commandString) - ENQUEUE (p->outputQueue, *commandString++); - ENQUEUE (p->outputQueue, '\r'); - - // get the transmit rolling - DEQUEUE (p->outputQueue, b); - outportb(p->uart, b); - - return 0; -} - - -static char *Modem_Response(ComPort *p) -{ - byte b; - - if (CheckStatus (p)) - return NULL; - - while (! EMPTY(p->inputQueue)) - { - DEQUEUE (p->inputQueue, b); - - if (p->bufferUsed == (sizeof(p->buffer) - 1)) - b = '\r'; - - if (b == '\r' && p->bufferUsed) - { - p->buffer[p->bufferUsed] = 0; - Con_Printf("%s\n", p->buffer); - SCR_UpdateScreen (); - p->bufferUsed = 0; - return p->buffer; - } - - if (b < ' ' || b > 'z') - continue; - p->buffer[p->bufferUsed] = b; - p->bufferUsed++; - } - - return NULL; -} - - -static void Modem_Hangup2(ComPort *p); -static void Modem_Hangup3(ComPort *p); -static void Modem_Hangup4(ComPort *p); - -static void Modem_Hangup(ComPort *p) -{ - Con_Printf("Hanging up modem...\n"); - disable(); - p->modemRang = false; - p->outputQueue.head = p->outputQueue.tail = 0; - p->inputQueue.head = p->inputQueue.tail = 0; - outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) & ~MCR_DTR); - enable(); - p->poll.procedure = Modem_Hangup2; - p->poll.arg = p; - SchedulePollProcedure(&p->poll, 1.5); -} - -static void Modem_Hangup2(ComPort *p) -{ - outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) | MCR_DTR); - Modem_Command(p, "+++"); - p->poll.procedure = Modem_Hangup3; - SchedulePollProcedure(&p->poll, 1.5); -} - -static void Modem_Hangup3(ComPort *p) -{ - Modem_Command(p, p->shutdown); - p->poll.procedure = Modem_Hangup4; - SchedulePollProcedure(&p->poll, 1.5); -} - -static void Modem_Hangup4(ComPort *p) -{ - Modem_Response(p); - Con_Printf("Hangup complete\n"); - p->modemConnected = false; -} +/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// net_comx.c
+
+#include <dos.h>
+#include <dpmi.h>
+
+#define NUM_COM_PORTS 2
+
+#define ERR_TTY_LINE_STATUS -1
+#define ERR_TTY_MODEM_STATUS -2
+#define ERR_TTY_NODATA -3
+
+#define QUEUESIZE 8192
+#define QUEUEMASK (QUEUESIZE - 1)
+
+typedef struct
+{
+ volatile int head;
+ volatile int tail;
+ volatile byte data[QUEUESIZE];
+} queue;
+
+#define FULL(q) (q.head == ((q.tail-1) & QUEUEMASK))
+#define EMPTY(q) (q.tail == q.head)
+#define ENQUEUE(q,b) (q.data[q.head] = b, q.head = (q.head + 1) & QUEUEMASK)
+#define DEQUEUE(q,b) (b = q.data[q.tail], q.tail = (q.tail + 1) & QUEUEMASK)
+
+extern cvar_t config_com_port;
+extern cvar_t config_com_irq;
+extern cvar_t config_com_baud;
+extern cvar_t config_com_modem;
+extern cvar_t config_modem_dialtype;
+extern cvar_t config_modem_clear;
+extern cvar_t config_modem_init;
+extern cvar_t config_modem_hangup;
+
+extern int m_return_state;
+extern int m_state;
+extern qboolean m_return_onerror;
+extern char m_return_reason[32];
+
+// 8250, 16550 definitions
+#define TRANSMIT_HOLDING_REGISTER 0x00
+#define RECEIVE_BUFFER_REGISTER 0x00
+#define INTERRUPT_ENABLE_REGISTER 0x01
+#define IER_RX_DATA_READY 0x01
+#define IER_TX_HOLDING_REGISTER_EMPTY 0x02
+#define IER_LINE_STATUS 0x04
+#define IER_MODEM_STATUS 0x08
+#define INTERRUPT_ID_REGISTER 0x02
+#define IIR_MODEM_STATUS_INTERRUPT 0x00
+#define IIR_TX_HOLDING_REGISTER_INTERRUPT 0x02
+#define IIR_RX_DATA_READY_INTERRUPT 0x04
+#define IIR_LINE_STATUS_INTERRUPT 0x06
+#define IIR_FIFO_TIMEOUT 0x0c
+#define IIR_FIFO_ENABLED 0xc0
+#define FIFO_CONTROL_REGISTER 0x02
+#define FCR_FIFO_ENABLE 0x01
+#define FCR_RCVR_FIFO_RESET 0x02
+#define FCR_XMIT_FIFO_RESET 0x04
+#define FCR_TRIGGER_01 0x00
+#define FCR_TRIGGER_04 0x40
+#define FCR_TRIGGER_08 0x80
+#define FCR_TRIGGER_16 0xc0
+#define LINE_CONTROL_REGISTER 0x03
+#define LCR_DATA_BITS_5 0x00
+#define LCR_DATA_BITS_6 0x01
+#define LCR_DATA_BITS_7 0x02
+#define LCR_DATA_BITS_8 0x03
+#define LCR_STOP_BITS_1 0x00
+#define LCR_STOP_BITS_2 0x04
+#define LCR_PARITY_NONE 0x00
+#define LCR_PARITY_ODD 0x08
+#define LCR_PARITY_EVEN 0x18
+#define LCR_PARITY_MARK 0x28
+#define LCR_PARITY_SPACE 0x38
+#define LCR_SET_BREAK 0x40
+#define LCR_DLAB 0x80
+#define MODEM_CONTROL_REGISTER 0x04
+#define MCR_DTR 0x01
+#define MCR_RTS 0x02
+#define MCR_OUT1 0x04
+#define MCR_OUT2 0x08
+#define MCR_LOOPBACK 0x10
+#define LINE_STATUS_REGISTER 0x05
+#define LSR_DATA_READY 0x01
+#define LSR_OVERRUN_ERROR 0x02
+#define LSR_PARITY_ERROR 0x04
+#define LSR_FRAMING_ERROR 0x08
+#define LSR_BREAK_DETECT 0x10
+#define LSR_TRANSMITTER_BUFFER_EMPTY 0x20
+#define LSR_TRANSMITTER_EMPTY 0x40
+#define LSR_FIFO_DIRTY 0x80
+#define MODEM_STATUS_REGISTER 0x06
+#define MSR_DELTA_CTS 0x01
+#define MSR_DELTA_DSR 0x02
+#define MSR_DELTA_RI 0x04
+#define MSR_DELTA_CD 0x08
+#define MSR_CTS 0x10
+#define MSR_DSR 0x20
+#define MSR_RI 0x40
+#define MSR_CD 0x80
+#define DIVISOR_LATCH_LOW 0x00
+#define DIVISOR_LATCH_HIGH 0x01
+
+#define MODEM_STATUS_MASK (MSR_CTS | MSR_DSR | MSR_CD)
+
+#define UART_AUTO 0
+#define UART_8250 1
+#define UART_16550 2
+
+static int ISA_uarts[] = {0x3f8,0x2f8,0x3e8,0x2e8};
+static int ISA_IRQs[] = {4,3,4,3};
+
+typedef struct ComPort_s
+{
+ struct ComPort_s *next;
+ _go32_dpmi_seginfo protectedModeInfo;
+ _go32_dpmi_seginfo protectedModeSaveInfo;
+ int uart;
+ volatile byte modemStatus;
+ byte modemStatusIgnore;
+ byte lineStatus;
+ byte bufferUsed;
+ qboolean enabled;
+ volatile qboolean statusUpdated;
+ qboolean useModem;
+ qboolean modemInitialized;
+ qboolean modemRang;
+ qboolean modemConnected;
+ queue inputQueue;
+ queue outputQueue;
+ char clear[16];
+ char startup[32];
+ char shutdown[16];
+ char buffer[128];
+ PollProcedure poll;
+ double timestamp;
+ byte uartType;
+ byte irq;
+ byte baudBits;
+ byte lineControl;
+ byte portNumber;
+ char dialType;
+ char name[4];
+} ComPort;
+
+ComPort *portList = NULL;
+ComPort *handleToPort [NUM_COM_PORTS];
+
+static int Modem_Command(ComPort *p, char *commandString);
+static char *Modem_Response(ComPort *p);
+static void Modem_Hangup(ComPort *p);
+
+int TTY_Init(void);
+void TTY_Shutdown(void);
+int TTY_Open(int serialPortNumber);
+void TTY_Close(int handle);
+int TTY_ReadByte(int handle);
+int TTY_WriteByte(int handle, byte data);
+void TTY_Flush(int handle);
+int TTY_Connect(int handle, char *host);
+void TTY_Disconnect(int handle);
+qboolean TTY_CheckForConnection(int handle);
+qboolean TTY_IsEnabled(int serialPortNumber);
+qboolean TTY_IsModem(int serialPortNumber);
+qboolean TTY_OutputQueueIsEmpty(int handle);
+
+static void ISR_8250 (ComPort *p)
+{
+ byte source = 0;
+ byte b;
+
+ disable();
+
+ while((source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07) != 1)
+ {
+ switch (source)
+ {
+ case IIR_RX_DATA_READY_INTERRUPT:
+ b = inportb (p->uart + RECEIVE_BUFFER_REGISTER);
+ if (! FULL(p->inputQueue))
+ {
+ ENQUEUE (p->inputQueue, b);
+ }
+ else
+ {
+ p->lineStatus |= LSR_OVERRUN_ERROR;
+ p->statusUpdated = true;
+ }
+ break;
+
+ case IIR_TX_HOLDING_REGISTER_INTERRUPT:
+ if (! EMPTY(p->outputQueue))
+ {
+ DEQUEUE (p->outputQueue, b);
+ outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b);
+ }
+ break;
+
+ case IIR_MODEM_STATUS_INTERRUPT:
+ p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
+ p->statusUpdated = true;
+ break;
+
+ case IIR_LINE_STATUS_INTERRUPT:
+ p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER);
+ p->statusUpdated = true;
+ break;
+ }
+ source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07;
+ }
+ outportb (0x20, 0x20);
+}
+
+static void COM1_ISR_8250 (void)
+{
+ ISR_8250 (handleToPort[0]);
+}
+
+static void COM2_ISR_8250 (void)
+{
+ ISR_8250 (handleToPort[1]);
+}
+
+
+
+static void ISR_16550 (ComPort *p)
+{
+ int count;
+ byte source;
+ byte b;
+
+ disable();
+ while((source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07) != 1)
+ {
+ switch (source)
+ {
+ case IIR_RX_DATA_READY_INTERRUPT:
+ do
+ {
+ b = inportb (p->uart + RECEIVE_BUFFER_REGISTER);
+ if (!FULL(p->inputQueue))
+ {
+ ENQUEUE (p->inputQueue, b);
+ }
+ else
+ {
+ p->lineStatus |= LSR_OVERRUN_ERROR;
+ p->statusUpdated = true;
+ }
+ } while (inportb (p->uart + LINE_STATUS_REGISTER) & LSR_DATA_READY);
+ break;
+
+ case IIR_TX_HOLDING_REGISTER_INTERRUPT:
+ count = 16;
+ while ((! EMPTY(p->outputQueue)) && count--)
+ {
+ DEQUEUE (p->outputQueue, b);
+ outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b);
+ }
+ break;
+
+ case IIR_MODEM_STATUS_INTERRUPT:
+ p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
+ p->statusUpdated = true;
+ break;
+
+ case IIR_LINE_STATUS_INTERRUPT:
+ p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER);
+ p->statusUpdated = true;
+ break;
+ }
+ source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07;
+ }
+
+ // check for lost IIR_TX_HOLDING_REGISTER_INTERRUPT on 16550a!
+ if (inportb (p->uart + LINE_STATUS_REGISTER ) & LSR_TRANSMITTER_EMPTY)
+ {
+ count = 16;
+ while ((! EMPTY(p->outputQueue)) && count--)
+ {
+ DEQUEUE (p->outputQueue, b);
+ outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b);
+ }
+ }
+
+ outportb (0x20, 0x20);
+}
+
+static void COM1_ISR_16550 (void)
+{
+ ISR_16550 (handleToPort[0]);
+}
+
+static void COM2_ISR_16550 (void)
+{
+ ISR_16550 (handleToPort[1]);
+}
+
+
+void TTY_GetComPortConfig (int portNumber, int *port, int *irq, int *baud, qboolean *useModem)
+{
+ ComPort *p;
+
+ p = handleToPort[portNumber];
+ *port = p->uart;
+ *irq = p->irq;
+ *baud = 115200 / p->baudBits;
+ *useModem = p->useModem;
+}
+
+void TTY_SetComPortConfig (int portNumber, int port, int irq, int baud, qboolean useModem)
+{
+ ComPort *p;
+ float temp;
+
+ if (useModem)
+ {
+ if (baud == 14400)
+ baud = 19200;
+ if (baud == 28800)
+ baud = 38400;
+ }
+
+ p = handleToPort[portNumber];
+ p->uart = port;
+ p->irq = irq;
+ p->baudBits = 115200 / baud;
+ p->useModem = useModem;
+
+ if (useModem)
+ temp = 1.0;
+ else
+ temp = 0.0;
+
+ Cvar_SetValue ("_config_com_port", (float)port);
+ Cvar_SetValue ("_config_com_irq", (float)irq);
+ Cvar_SetValue ("_config_com_baud", (float)baud);
+ Cvar_SetValue ("_config_com_modem", temp);
+}
+
+void TTY_GetModemConfig (int portNumber, char *dialType, char *clear, char *init, char *hangup)
+{
+ ComPort *p;
+
+ p = handleToPort[portNumber];
+ *dialType = p->dialType;
+ Q_strcpy(clear, p->clear);
+ Q_strcpy(init, p->startup);
+ Q_strcpy(hangup, p->shutdown);
+}
+
+void TTY_SetModemConfig (int portNumber, char *dialType, char *clear, char *init, char *hangup)
+{
+ ComPort *p;
+
+ p = handleToPort[portNumber];
+ p->dialType = dialType[0];
+ Q_strcpy(p->clear, clear);
+ Q_strcpy(p->startup, init);
+ Q_strcpy(p->shutdown, hangup);
+
+ p->modemInitialized = false;
+
+ Cvar_Set ("_config_modem_dialtype", dialType);
+ Cvar_Set ("_config_modem_clear", clear);
+ Cvar_Set ("_config_modem_init", init);
+ Cvar_Set ("_config_modem_hangup", hangup);
+}
+
+
+static void ResetComPortConfig (ComPort *p)
+{
+ p->useModem = false;
+ p->uartType = UART_AUTO;
+ p->uart = ISA_uarts[p->portNumber];
+ p->irq = ISA_IRQs[p->portNumber];
+ p->modemStatusIgnore = MSR_CD | MSR_CTS | MSR_DSR;
+ p->baudBits = 115200 / 57600;
+ p->lineControl = LCR_DATA_BITS_8 | LCR_STOP_BITS_1 | LCR_PARITY_NONE;
+ Q_strcpy(p->clear, "ATZ");
+ Q_strcpy(p->startup, "");
+ Q_strcpy(p->shutdown, "AT H");
+ p->modemRang = false;
+ p->modemConnected = false;
+ p->statusUpdated = false;
+ p->outputQueue.head = p->outputQueue.tail = 0;
+ p->inputQueue.head = p->inputQueue.tail = 0;
+}
+
+
+static void ComPort_Enable(ComPort *p)
+{
+ void (*isr)(void);
+ int n;
+ byte b;
+
+ if (p->enabled)
+ {
+ Con_Printf("Already enabled\n");
+ return;
+ }
+
+ // disable all UART interrupts
+ outportb (p->uart + INTERRUPT_ENABLE_REGISTER, 0);
+
+ // clear out any buffered uncoming data
+ while((inportb (p->uart + LINE_STATUS_REGISTER)) & LSR_DATA_READY)
+ inportb (p->uart + RECEIVE_BUFFER_REGISTER);
+
+ // get the current line and modem status
+ p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
+ p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER);
+
+ // clear any UART interrupts
+ do
+ {
+ n = inportb (p->uart + INTERRUPT_ID_REGISTER) & 7;
+ if (n == IIR_RX_DATA_READY_INTERRUPT)
+ inportb (p->uart + RECEIVE_BUFFER_REGISTER);
+ } while (!(n & 1));
+
+ if (p->uartType == UART_AUTO)
+ {
+ outportb (p->uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE);
+ b = inportb (p->uart + INTERRUPT_ID_REGISTER);
+ if ((b & IIR_FIFO_ENABLED) == IIR_FIFO_ENABLED)
+ p->uartType = UART_16550;
+ else
+ p->uartType = UART_8250;
+ }
+
+ // save the old interrupt handler
+ _go32_dpmi_get_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeSaveInfo);
+
+ if (p->uartType == UART_8250)
+ {
+ outportb (p->uart + FIFO_CONTROL_REGISTER, 0);
+ if (p == handleToPort[0])
+ isr = COM1_ISR_8250;
+ else
+ isr = COM2_ISR_8250;
+ }
+ else
+ {
+ outportb (p->uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE | FCR_RCVR_FIFO_RESET | FCR_XMIT_FIFO_RESET | FCR_TRIGGER_08);
+ if (p == handleToPort[0])
+ isr = COM1_ISR_16550;
+ else
+ isr = COM2_ISR_16550;
+ }
+
+ p->protectedModeInfo.pm_offset = (int)isr;
+
+ n = _go32_dpmi_allocate_iret_wrapper(&p->protectedModeInfo);
+ if (n)
+ {
+ Con_Printf("serial: protected mode callback allocation failed\n");
+ return;
+ }
+
+ // disable interrupts at the processor
+ disable();
+
+ // install our interrupt handlers now
+ _go32_dpmi_set_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeInfo);
+
+ // enable our interrupt at the PIC
+ outportb (0x21, inportb (0x21) & ~(1<<p->irq));
+
+ // enable interrupts at the processor
+ enable();
+
+ // enable interrupts at the PIC
+ outportb (0x20, 0xc2);
+
+ // set baud rate & line control
+ outportb (p->uart + LINE_CONTROL_REGISTER, LCR_DLAB | p->lineControl);
+ outportb (p->uart, p->baudBits);
+ outportb (p->uart + 1, 0);
+ outportb (p->uart + LINE_CONTROL_REGISTER, p->lineControl);
+
+ // set modem control register & enable uart interrupt generation
+ outportb(p->uart + MODEM_CONTROL_REGISTER, MCR_OUT2 | MCR_RTS | MCR_DTR);
+
+ // enable the individual interrupts at the uart
+ outportb (p->uart + INTERRUPT_ENABLE_REGISTER, IER_RX_DATA_READY | IER_TX_HOLDING_REGISTER_EMPTY | IER_LINE_STATUS | IER_MODEM_STATUS);
+
+ p->enabled = true;
+}
+
+
+static void ComPort_Disable(ComPort *p)
+{
+ if (!p->enabled)
+ {
+ Con_Printf("Already disabled\n");
+ return;
+ }
+
+ // disable interrupts at the uart
+ outportb (p->uart + INTERRUPT_ENABLE_REGISTER, 0);
+
+ // disable our interrupt at the PIC
+ outportb (0x21, inportb (0x21) | (1<<p->irq));
+
+ // disable interrupts at the processor
+ disable();
+
+ // restore the old interrupt handler
+ _go32_dpmi_set_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeSaveInfo);
+ _go32_dpmi_free_iret_wrapper(&p->protectedModeInfo);
+
+ // enable interrupts at the processor
+ enable();
+
+ p->enabled = false;
+}
+
+
+static int CheckStatus (ComPort *p)
+{
+ int ret = 0;
+
+ if (p->statusUpdated)
+ {
+ p->statusUpdated = false;
+
+ if (p->lineStatus & (LSR_OVERRUN_ERROR | LSR_PARITY_ERROR | LSR_FRAMING_ERROR | LSR_BREAK_DETECT))
+ {
+ if (p->lineStatus & LSR_OVERRUN_ERROR)
+ Con_DPrintf ("Serial overrun error\n");
+ if (p->lineStatus & LSR_PARITY_ERROR)
+ Con_DPrintf ("Serial parity error\n");
+ if (p->lineStatus & LSR_FRAMING_ERROR)
+ Con_DPrintf ("Serial framing error\n");
+ if (p->lineStatus & LSR_BREAK_DETECT)
+ Con_DPrintf ("Serial break detect\n");
+ ret = ERR_TTY_LINE_STATUS;
+ }
+
+ if ((p->modemStatus & MODEM_STATUS_MASK) != MODEM_STATUS_MASK)
+ {
+ if (!(p->modemStatus & MSR_CTS))
+ Con_Printf ("Serial lost CTS\n");
+ if (!(p->modemStatus & MSR_DSR))
+ Con_Printf ("Serial lost DSR\n");
+ if (!(p->modemStatus & MSR_CD))
+ Con_Printf ("Serial lost Carrier\n");
+ ret = ERR_TTY_MODEM_STATUS;
+ }
+ }
+
+ return ret;
+}
+
+
+static void Modem_Init(ComPort *p)
+{
+ double start;
+ char *response;
+
+ Con_Printf ("Initializing modem...\n");
+
+ // write 0 to MCR, wait 1/2 sec, then write the real value back again
+ // I got this from the guys at head-to-head who say it's necessary.
+ outportb(p->uart + MODEM_CONTROL_REGISTER, 0);
+ start = Sys_FloatTime();
+ while ((Sys_FloatTime() - start) < 0.5)
+ ;
+ outportb(p->uart + MODEM_CONTROL_REGISTER, MCR_OUT2 | MCR_RTS | MCR_DTR);
+ start = Sys_FloatTime();
+ while ((Sys_FloatTime() - start) < 0.25)
+ ;
+
+ if (*p->clear)
+ {
+ Modem_Command (p, p->clear);
+ start = Sys_FloatTime();
+ while(1)
+ {
+ if ((Sys_FloatTime() - start) > 3.0)
+ {
+ Con_Printf("No response - clear failed\n");
+ p->enabled = false;
+ goto failed;
+ }
+ response = Modem_Response(p);
+ if (!response)
+ continue;
+ if (Q_strncmp(response, "OK", 2) == 0)
+ break;
+ if (Q_strncmp(response, "ERROR", 5) == 0)
+ {
+ p->enabled = false;
+ goto failed;
+ }
+ }
+ }
+
+ if (*p->startup)
+ {
+ Modem_Command (p, p->startup);
+ start = Sys_FloatTime();
+ while(1)
+ {
+ if ((Sys_FloatTime() - start) > 3.0)
+ {
+ Con_Printf("No response - init failed\n");
+ p->enabled = false;
+ goto failed;
+ }
+ response = Modem_Response(p);
+ if (!response)
+ continue;
+ if (Q_strncmp(response, "OK", 2) == 0)
+ break;
+ if (Q_strncmp(response, "ERROR", 5) == 0)
+ {
+ p->enabled = false;
+ goto failed;
+ }
+ }
+ }
+
+ p->modemInitialized = true;
+ return;
+
+failed:
+ if (m_return_onerror)
+ {
+ key_dest = key_menu;
+ m_state = m_return_state;
+ m_return_onerror = false;
+ Q_strcpy(m_return_reason, "Initialization Failed");
+ }
+ return;
+}
+
+
+void TTY_Enable(int handle)
+{
+ ComPort *p;
+
+ p = handleToPort [handle];
+ if (p->enabled)
+ return;
+
+ ComPort_Enable(p);
+
+ if (p->useModem && !p->modemInitialized)
+ Modem_Init (p);
+}
+
+
+int TTY_Open(int serialPortNumber)
+{
+ return serialPortNumber;
+}
+
+
+void TTY_Close(int handle)
+{
+ ComPort *p;
+ double startTime;
+
+ p = handleToPort [handle];
+
+ startTime = Sys_FloatTime();
+ while ((Sys_FloatTime() - startTime) < 1.0)
+ if (EMPTY(p->outputQueue))
+ break;
+
+ if (p->useModem)
+ {
+ if (p->modemConnected)
+ Modem_Hangup(p);
+ }
+}
+
+
+int TTY_ReadByte(int handle)
+{
+ int ret;
+ ComPort *p;
+
+ p = handleToPort [handle];
+
+ if ((ret = CheckStatus (p)) != 0)
+ return ret;
+
+ if (EMPTY (p->inputQueue))
+ return ERR_TTY_NODATA;
+
+ DEQUEUE (p->inputQueue, ret);
+ return (ret & 0xff);
+}
+
+
+int TTY_WriteByte(int handle, byte data)
+{
+ ComPort *p;
+
+ p = handleToPort [handle];
+ if (FULL(p->outputQueue))
+ return -1;
+
+ ENQUEUE (p->outputQueue, data);
+ return 0;
+}
+
+
+void TTY_Flush(int handle)
+{
+ byte b;
+ ComPort *p;
+
+ p = handleToPort [handle];
+
+ if (inportb (p->uart + LINE_STATUS_REGISTER ) & LSR_TRANSMITTER_EMPTY)
+ {
+ DEQUEUE (p->outputQueue, b);
+ outportb(p->uart, b);
+ }
+}
+
+
+int TTY_Connect(int handle, char *host)
+{
+ double start;
+ ComPort *p;
+ char *response = NULL;
+ keydest_t save_key_dest;
+ byte dialstring[64];
+ byte b;
+
+ p = handleToPort[handle];
+
+ if ((p->modemStatus & MODEM_STATUS_MASK) != MODEM_STATUS_MASK)
+ {
+ Con_Printf ("Serial: line not ready (");
+ if ((p->modemStatus & MSR_CTS) == 0)
+ Con_Printf(" CTS");
+ if ((p->modemStatus & MSR_DSR) == 0)
+ Con_Printf(" DSR");
+ if ((p->modemStatus & MSR_CD) == 0)
+ Con_Printf(" CD");
+ Con_Printf(" )");
+ return -1;
+ }
+
+ // discard any scraps in the input buffer
+ while (! EMPTY (p->inputQueue))
+ DEQUEUE (p->inputQueue, b);
+
+ CheckStatus (p);
+
+ if (p->useModem)
+ {
+ save_key_dest = key_dest;
+ key_dest = key_console;
+ key_count = -2;
+
+ Con_Printf ("Dialing...\n");
+ sprintf(dialstring, "AT D%c %s\r", p->dialType, host);
+ Modem_Command (p, dialstring);
+ start = Sys_FloatTime();
+ while(1)
+ {
+ if ((Sys_FloatTime() - start) > 60.0)
+ {
+ Con_Printf("Dialing failure!\n");
+ break;
+ }
+
+ Sys_SendKeyEvents ();
+ if (key_count == 0)
+ {
+ if (key_lastpress != K_ESCAPE)
+ {
+ key_count = -2;
+ continue;
+ }
+ Con_Printf("Aborting...\n");
+ while ((Sys_FloatTime() - start) < 5.0)
+ ;
+ disable();
+ p->outputQueue.head = p->outputQueue.tail = 0;
+ p->inputQueue.head = p->inputQueue.tail = 0;
+ outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) & ~MCR_DTR);
+ enable();
+ start = Sys_FloatTime();
+ while ((Sys_FloatTime() - start) < 0.75)
+ ;
+ outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) | MCR_DTR);
+ response = "Aborted";
+ break;
+ }
+
+ response = Modem_Response(p);
+ if (!response)
+ continue;
+ if (Q_strncmp(response, "CONNECT", 7) == 0)
+ {
+ disable();
+ p->modemRang = true;
+ p->modemConnected = true;
+ p->outputQueue.head = p->outputQueue.tail = 0;
+ p->inputQueue.head = p->inputQueue.tail = 0;
+ enable();
+ key_dest = save_key_dest;
+ key_count = 0;
+ m_return_onerror = false;
+ return 0;
+ }
+ if (Q_strncmp(response, "NO CARRIER", 10) == 0)
+ break;
+ if (Q_strncmp(response, "NO DIALTONE", 11) == 0)
+ break;
+ if (Q_strncmp(response, "NO DIAL TONE", 12) == 0)
+ break;
+ if (Q_strncmp(response, "NO ANSWER", 9) == 0)
+ break;
+ if (Q_strncmp(response, "BUSY", 4) == 0)
+ break;
+ if (Q_strncmp(response, "ERROR", 5) == 0)
+ break;
+ }
+ key_dest = save_key_dest;
+ key_count = 0;
+ if (m_return_onerror)
+ {
+ key_dest = key_menu;
+ m_state = m_return_state;
+ m_return_onerror = false;
+ Q_strncpy(m_return_reason, response, 31);
+ }
+ return -1;
+ }
+ m_return_onerror = false;
+ return 0;
+}
+
+
+void TTY_Disconnect(int handle)
+{
+ ComPort *p;
+
+ p = handleToPort[handle];
+
+ if (p->useModem && p->modemConnected)
+ Modem_Hangup(p);
+}
+
+
+qboolean TTY_CheckForConnection(int handle)
+{
+ ComPort *p;
+
+ p = handleToPort[handle];
+
+ CheckStatus (p);
+
+ if (p->useModem)
+ {
+ if (!p->modemRang)
+ {
+ if (!Modem_Response(p))
+ return false;
+
+ if (Q_strncmp(p->buffer, "RING", 4) == 0)
+ {
+ Modem_Command (p, "ATA");
+ p->modemRang = true;
+ p->timestamp = net_time;
+ }
+ return false;
+ }
+ if (!p->modemConnected)
+ {
+ if ((net_time - p->timestamp) > 35.0)
+ {
+ Con_Printf("Unable to establish modem connection\n");
+ p->modemRang = false;
+ return false;
+ }
+
+ if (!Modem_Response(p))
+ return false;
+
+ if (Q_strncmp (p->buffer, "CONNECT", 7) != 0)
+ return false;
+
+ disable();
+ p->modemConnected = true;
+ p->outputQueue.head = p->outputQueue.tail = 0;
+ p->inputQueue.head = p->inputQueue.tail = 0;
+ enable();
+ Con_Printf("Modem Connect\n");
+ return true;
+ }
+ return true;
+ }
+
+ // direct connect case
+ if (EMPTY (p->inputQueue))
+ return false;
+ return true;
+}
+
+
+qboolean TTY_IsEnabled(int serialPortNumber)
+{
+ return handleToPort[serialPortNumber]->enabled;
+}
+
+
+qboolean TTY_IsModem(int serialPortNumber)
+{
+ return handleToPort[serialPortNumber]->useModem;
+}
+
+
+qboolean TTY_OutputQueueIsEmpty(int handle)
+{
+ return EMPTY(handleToPort[handle]->outputQueue);
+}
+
+
+void Com_f (void)
+{
+ ComPort *p;
+ int portNumber;
+ int i;
+ int n;
+
+ // first, determine which port they're messing with
+ portNumber = Q_atoi(Cmd_Argv (0) + 3) - 1;
+ if (portNumber > 1)
+ return;
+ p = handleToPort[portNumber];
+
+ if (Cmd_Argc() == 1)
+ {
+ Con_Printf("Settings for COM%i\n", portNumber + 1);
+ Con_Printf("enabled: %s\n", p->enabled ? "true" : "false");
+ Con_Printf("uart: ");
+ if (p->uartType == UART_AUTO)
+ Con_Printf("auto\n");
+ else if (p->uartType == UART_8250)
+ Con_Printf("8250\n");
+ else
+ Con_Printf("16550\n");
+ Con_Printf("port: %x\n", p->uart);
+ Con_Printf("irq: %i\n", p->irq);
+ Con_Printf("baud: %i\n", 115200 / p->baudBits);
+ Con_Printf("CTS: %s\n", (p->modemStatusIgnore & MSR_CTS) ? "ignored" : "honored");
+ Con_Printf("DSR: %s\n", (p->modemStatusIgnore & MSR_DSR) ? "ignored" : "honored");
+ Con_Printf("CD: %s\n", (p->modemStatusIgnore & MSR_CD) ? "ignored" : "honored");
+ if (p->useModem)
+ {
+ Con_Printf("type: Modem\n");
+ Con_Printf("clear: %s\n", p->clear);
+ Con_Printf("startup: %s\n", p->startup);
+ Con_Printf("shutdown: %s\n", p->shutdown);
+ }
+ else
+ Con_Printf("type: Direct connect\n");
+
+ return;
+ }
+
+
+ if (Cmd_CheckParm ("disable"))
+ {
+ if (p->enabled)
+ ComPort_Disable(p);
+ p->modemInitialized = false;
+ return;
+ }
+
+ if (Cmd_CheckParm ("reset"))
+ {
+ ComPort_Disable(p);
+ ResetComPortConfig (p);
+ return;
+ }
+
+ if ((i = Cmd_CheckParm ("port")) != 0)
+ {
+ if (p->enabled)
+ {
+ Con_Printf("COM port must be disabled to change port\n");
+ return;
+ }
+ p->uart = Q_atoi (Cmd_Argv (i+1));
+ }
+
+ if ((i = Cmd_CheckParm ("irq")) != 0)
+ {
+ if (p->enabled)
+ {
+ Con_Printf("COM port must be disabled to change irq\n");
+ return;
+ }
+ p->irq = Q_atoi (Cmd_Argv (i+1));
+ }
+
+ if ((i = Cmd_CheckParm ("baud")) != 0)
+ {
+ if (p->enabled)
+ {
+ Con_Printf("COM port must be disabled to change baud\n");
+ return;
+ }
+ n = Q_atoi (Cmd_Argv (i+1));
+ if (n == 0)
+ Con_Printf("Invalid baud rate specified\n");
+ else
+ p->baudBits = 115200 / n;
+ }
+
+ if (Cmd_CheckParm ("8250"))
+ {
+ if (p->enabled)
+ {
+ Con_Printf("COM port must be disabled to change uart\n");
+ return;
+ }
+ p->uartType = UART_8250;
+ }
+ if (Cmd_CheckParm ("16550"))
+ {
+ if (p->enabled)
+ {
+ Con_Printf("COM port must be disabled to change uart\n");
+ return;
+ }
+ p->uartType = UART_16550;
+ }
+ if (Cmd_CheckParm ("auto"))
+ {
+ if (p->enabled)
+ {
+ Con_Printf("COM port must be disabled to change uart\n");
+ return;
+ }
+ p->uartType = UART_AUTO;
+ }
+
+ if (Cmd_CheckParm ("pulse"))
+ p->dialType = 'P';
+ if (Cmd_CheckParm ("tone"))
+ p->dialType = 'T';
+
+ if (Cmd_CheckParm ("direct"))
+ p->useModem = false;
+ if (Cmd_CheckParm ("modem"))
+ p->useModem = true;
+
+ if ((i = Cmd_CheckParm ("clear")) != 0)
+ {
+ Q_strncpy (p->clear, Cmd_Argv (i+1), 16);
+ }
+
+ if ((i = Cmd_CheckParm ("startup")) != 0)
+ {
+ Q_strncpy (p->startup, Cmd_Argv (i+1), 32);
+ p->modemInitialized = false;
+ }
+
+ if ((i = Cmd_CheckParm ("shutdown")) != 0)
+ {
+ Q_strncpy (p->shutdown, Cmd_Argv (i+1), 16);
+ }
+
+ if (Cmd_CheckParm ("-cts"))
+ {
+ p->modemStatusIgnore |= MSR_CTS;
+ p->modemStatus |= MSR_CTS;
+ }
+
+ if (Cmd_CheckParm ("+cts"))
+ {
+ p->modemStatusIgnore &= (~MSR_CTS);
+ p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
+ }
+
+ if (Cmd_CheckParm ("-dsr"))
+ {
+ p->modemStatusIgnore |= MSR_DSR;
+ p->modemStatus |= MSR_DSR;
+ }
+
+ if (Cmd_CheckParm ("+dsr"))
+ {
+ p->modemStatusIgnore &= (~MSR_DSR);
+ p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
+ }
+
+ if (Cmd_CheckParm ("-cd"))
+ {
+ p->modemStatusIgnore |= MSR_CD;
+ p->modemStatus |= MSR_CD;
+ }
+
+ if (Cmd_CheckParm ("+cd"))
+ {
+ p->modemStatusIgnore &= (~MSR_CD);
+ p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
+ }
+
+ if (Cmd_CheckParm ("enable"))
+ {
+ if (!p->enabled)
+ ComPort_Enable(p);
+ if (p->useModem && !p->modemInitialized)
+ Modem_Init (p);
+ }
+}
+
+
+int TTY_Init(void)
+{
+ int n;
+ ComPort *p;
+
+ for (n = 0; n < NUM_COM_PORTS; n++)
+ {
+ p = (ComPort *)Hunk_AllocName(sizeof(ComPort), "comport");
+ if (p == NULL)
+ Sys_Error("Hunk alloc failed for com port\n");
+ p->next = portList;
+ portList = p;
+ handleToPort[n] = p;
+ p->portNumber = n;
+ p->dialType = 'T';
+ sprintf(p->name, "com%u", n+1);
+ Cmd_AddCommand (p->name, Com_f);
+ ResetComPortConfig (p);
+ }
+
+ GetComPortConfig = TTY_GetComPortConfig;
+ SetComPortConfig = TTY_SetComPortConfig;
+ GetModemConfig = TTY_GetModemConfig;
+ SetModemConfig = TTY_SetModemConfig;
+
+ return 0;
+}
+
+
+void TTY_Shutdown(void)
+{
+ int n;
+ ComPort *p;
+
+ for (n = 0; n < NUM_COM_PORTS; n++)
+ {
+ p = handleToPort[n];
+ if (p->enabled)
+ {
+ while (p->modemConnected)
+ NET_Poll();
+ ComPort_Disable (p);
+ }
+ }
+}
+
+
+static int Modem_Command(ComPort *p, char *commandString)
+{
+ byte b;
+
+ if (CheckStatus (p))
+ return -1;
+
+ disable();
+ p->outputQueue.head = p->outputQueue.tail = 0;
+ p->inputQueue.head = p->inputQueue.tail = 0;
+ enable();
+ p->bufferUsed = 0;
+
+ while (*commandString)
+ ENQUEUE (p->outputQueue, *commandString++);
+ ENQUEUE (p->outputQueue, '\r');
+
+ // get the transmit rolling
+ DEQUEUE (p->outputQueue, b);
+ outportb(p->uart, b);
+
+ return 0;
+}
+
+
+static char *Modem_Response(ComPort *p)
+{
+ byte b;
+
+ if (CheckStatus (p))
+ return NULL;
+
+ while (! EMPTY(p->inputQueue))
+ {
+ DEQUEUE (p->inputQueue, b);
+
+ if (p->bufferUsed == (sizeof(p->buffer) - 1))
+ b = '\r';
+
+ if (b == '\r' && p->bufferUsed)
+ {
+ p->buffer[p->bufferUsed] = 0;
+ Con_Printf("%s\n", p->buffer);
+ SCR_UpdateScreen ();
+ p->bufferUsed = 0;
+ return p->buffer;
+ }
+
+ if (b < ' ' || b > 'z')
+ continue;
+ p->buffer[p->bufferUsed] = b;
+ p->bufferUsed++;
+ }
+
+ return NULL;
+}
+
+
+static void Modem_Hangup2(ComPort *p);
+static void Modem_Hangup3(ComPort *p);
+static void Modem_Hangup4(ComPort *p);
+
+static void Modem_Hangup(ComPort *p)
+{
+ Con_Printf("Hanging up modem...\n");
+ disable();
+ p->modemRang = false;
+ p->outputQueue.head = p->outputQueue.tail = 0;
+ p->inputQueue.head = p->inputQueue.tail = 0;
+ outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) & ~MCR_DTR);
+ enable();
+ p->poll.procedure = Modem_Hangup2;
+ p->poll.arg = p;
+ SchedulePollProcedure(&p->poll, 1.5);
+}
+
+static void Modem_Hangup2(ComPort *p)
+{
+ outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) | MCR_DTR);
+ Modem_Command(p, "+++");
+ p->poll.procedure = Modem_Hangup3;
+ SchedulePollProcedure(&p->poll, 1.5);
+}
+
+static void Modem_Hangup3(ComPort *p)
+{
+ Modem_Command(p, p->shutdown);
+ p->poll.procedure = Modem_Hangup4;
+ SchedulePollProcedure(&p->poll, 1.5);
+}
+
+static void Modem_Hangup4(ComPort *p)
+{
+ Modem_Response(p);
+ Con_Printf("Hangup complete\n");
+ p->modemConnected = false;
+}
|
