12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286 |
- /*
- 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;
- }
|