Annotation of quake1/net_comx.c, revision 1.1

1.1     ! root        1: // net_comx.c
        !             2: 
        !             3: #include <dos.h>
        !             4: #include <dpmi.h>
        !             5: 
        !             6: #define NUM_COM_PORTS  2
        !             7: 
        !             8: #define ERR_TTY_LINE_STATUS            -1
        !             9: #define ERR_TTY_MODEM_STATUS   -2
        !            10: #define ERR_TTY_NODATA                 -3
        !            11: 
        !            12: #define QUEUESIZE      8192
        !            13: #define QUEUEMASK      (QUEUESIZE - 1)
        !            14: 
        !            15: typedef struct
        !            16: {
        !            17:        volatile int  head;
        !            18:        volatile int  tail;
        !            19:        volatile byte data[QUEUESIZE];
        !            20: } queue;
        !            21: 
        !            22: #define FULL(q)                        (q.head == ((q.tail-1) & QUEUEMASK))
        !            23: #define EMPTY(q)               (q.tail == q.head)
        !            24: #define ENQUEUE(q,b)   (q.data[q.head] = b, q.head = (q.head + 1) & QUEUEMASK)
        !            25: #define DEQUEUE(q,b)   (b = q.data[q.tail], q.tail = (q.tail + 1) & QUEUEMASK)
        !            26: 
        !            27: extern cvar_t  config_com_port;
        !            28: extern cvar_t  config_com_irq;
        !            29: extern cvar_t  config_com_baud;
        !            30: extern cvar_t  config_com_modem;
        !            31: extern cvar_t  config_modem_dialtype;
        !            32: extern cvar_t  config_modem_clear;
        !            33: extern cvar_t  config_modem_init;
        !            34: extern cvar_t  config_modem_hangup;
        !            35: 
        !            36: extern int m_return_state;
        !            37: extern int m_state;
        !            38: extern qboolean m_return_onerror;
        !            39: extern char m_return_reason[32];
        !            40: 
        !            41: // 8250, 16550 definitions
        !            42: #define TRANSMIT_HOLDING_REGISTER            0x00
        !            43: #define RECEIVE_BUFFER_REGISTER              0x00
        !            44: #define INTERRUPT_ENABLE_REGISTER            0x01
        !            45: #define   IER_RX_DATA_READY                  0x01
        !            46: #define   IER_TX_HOLDING_REGISTER_EMPTY      0x02
        !            47: #define   IER_LINE_STATUS                    0x04
        !            48: #define   IER_MODEM_STATUS                   0x08
        !            49: #define INTERRUPT_ID_REGISTER                0x02
        !            50: #define   IIR_MODEM_STATUS_INTERRUPT         0x00
        !            51: #define   IIR_TX_HOLDING_REGISTER_INTERRUPT  0x02
        !            52: #define   IIR_RX_DATA_READY_INTERRUPT        0x04
        !            53: #define   IIR_LINE_STATUS_INTERRUPT          0x06
        !            54: #define   IIR_FIFO_TIMEOUT                   0x0c
        !            55: #define   IIR_FIFO_ENABLED                   0xc0
        !            56: #define FIFO_CONTROL_REGISTER                0x02
        !            57: #define   FCR_FIFO_ENABLE                    0x01
        !            58: #define   FCR_RCVR_FIFO_RESET                0x02
        !            59: #define   FCR_XMIT_FIFO_RESET                0x04
        !            60: #define   FCR_TRIGGER_01                     0x00
        !            61: #define   FCR_TRIGGER_04                     0x40
        !            62: #define   FCR_TRIGGER_08                     0x80
        !            63: #define   FCR_TRIGGER_16                     0xc0
        !            64: #define LINE_CONTROL_REGISTER                0x03
        !            65: #define   LCR_DATA_BITS_5                    0x00
        !            66: #define   LCR_DATA_BITS_6                    0x01
        !            67: #define   LCR_DATA_BITS_7                    0x02
        !            68: #define   LCR_DATA_BITS_8                    0x03
        !            69: #define   LCR_STOP_BITS_1                    0x00
        !            70: #define   LCR_STOP_BITS_2                    0x04
        !            71: #define   LCR_PARITY_NONE                    0x00
        !            72: #define   LCR_PARITY_ODD                     0x08
        !            73: #define   LCR_PARITY_EVEN                    0x18
        !            74: #define   LCR_PARITY_MARK                    0x28
        !            75: #define   LCR_PARITY_SPACE                   0x38
        !            76: #define   LCR_SET_BREAK                      0x40
        !            77: #define   LCR_DLAB                           0x80
        !            78: #define MODEM_CONTROL_REGISTER               0x04
        !            79: #define   MCR_DTR                            0x01
        !            80: #define   MCR_RTS                            0x02
        !            81: #define   MCR_OUT1                           0x04
        !            82: #define   MCR_OUT2                           0x08
        !            83: #define   MCR_LOOPBACK                       0x10
        !            84: #define LINE_STATUS_REGISTER                 0x05
        !            85: #define   LSR_DATA_READY                     0x01
        !            86: #define   LSR_OVERRUN_ERROR                  0x02
        !            87: #define   LSR_PARITY_ERROR                   0x04
        !            88: #define   LSR_FRAMING_ERROR                  0x08
        !            89: #define   LSR_BREAK_DETECT                   0x10
        !            90: #define   LSR_TRANSMITTER_BUFFER_EMPTY       0x20
        !            91: #define   LSR_TRANSMITTER_EMPTY              0x40
        !            92: #define   LSR_FIFO_DIRTY                     0x80
        !            93: #define MODEM_STATUS_REGISTER                0x06
        !            94: #define   MSR_DELTA_CTS                      0x01
        !            95: #define   MSR_DELTA_DSR                      0x02
        !            96: #define   MSR_DELTA_RI                       0x04
        !            97: #define   MSR_DELTA_CD                       0x08
        !            98: #define   MSR_CTS                            0x10
        !            99: #define   MSR_DSR                            0x20
        !           100: #define   MSR_RI                             0x40
        !           101: #define   MSR_CD                             0x80
        !           102: #define DIVISOR_LATCH_LOW                    0x00
        !           103: #define DIVISOR_LATCH_HIGH                   0x01
        !           104: 
        !           105: #define MODEM_STATUS_MASK      (MSR_CTS | MSR_DSR | MSR_CD)
        !           106: 
        !           107: #define UART_AUTO      0
        !           108: #define UART_8250      1
        !           109: #define UART_16550     2
        !           110: 
        !           111: static int ISA_uarts[] = {0x3f8,0x2f8,0x3e8,0x2e8};
        !           112: static int ISA_IRQs[]  = {4,3,4,3};
        !           113: 
        !           114: typedef struct ComPort_s
        !           115: {
        !           116:        struct ComPort_s                *next;
        !           117:        _go32_dpmi_seginfo              protectedModeInfo;
        !           118:        _go32_dpmi_seginfo              protectedModeSaveInfo;
        !           119:        int                                             uart;
        !           120:        volatile byte                   modemStatus;
        !           121:        byte                                    modemStatusIgnore;
        !           122:        byte                                    lineStatus;
        !           123:        byte                                    bufferUsed;
        !           124:        qboolean                                enabled;
        !           125:        volatile qboolean               statusUpdated;
        !           126:        qboolean                                useModem;
        !           127:        qboolean                                modemInitialized;
        !           128:        qboolean                                modemRang;
        !           129:        qboolean                                modemConnected;
        !           130:        queue                                   inputQueue;
        !           131:        queue                                   outputQueue;
        !           132:        char                                    clear[16];
        !           133:        char                                    startup[32];
        !           134:        char                                    shutdown[16];
        !           135:        char                                    buffer[128];
        !           136:        PollProcedure                   poll;
        !           137:        double                                  timestamp;
        !           138:        byte                                    uartType;
        !           139:        byte                                    irq;
        !           140:        byte                                    baudBits;
        !           141:        byte                                    lineControl;
        !           142:        byte                                    portNumber;
        !           143:        char                                    dialType;
        !           144:        char                                    name[4];
        !           145: } ComPort;
        !           146: 
        !           147: ComPort *portList = NULL;
        !           148: ComPort *handleToPort [NUM_COM_PORTS];
        !           149: 
        !           150: static int Modem_Command(ComPort *p, char *commandString);
        !           151: static char *Modem_Response(ComPort *p);
        !           152: static void Modem_Hangup(ComPort *p);
        !           153: 
        !           154: int TTY_Init(void);
        !           155: void TTY_Shutdown(void);
        !           156: int TTY_Open(int serialPortNumber);
        !           157: void TTY_Close(int handle);
        !           158: int TTY_ReadByte(int handle);
        !           159: int TTY_WriteByte(int handle, byte data);
        !           160: void TTY_Flush(int handle);
        !           161: int TTY_Connect(int handle, char *host);
        !           162: void TTY_Disconnect(int handle);
        !           163: qboolean TTY_CheckForConnection(int handle);
        !           164: qboolean TTY_IsEnabled(int serialPortNumber);
        !           165: qboolean TTY_IsModem(int serialPortNumber);
        !           166: qboolean TTY_OutputQueueIsEmpty(int handle);
        !           167: 
        !           168: static void ISR_8250 (ComPort *p)
        !           169: {
        !           170:        byte    source = 0;
        !           171:        byte    b;
        !           172: 
        !           173:        disable();
        !           174: 
        !           175:        while((source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07) != 1)
        !           176:        {
        !           177:                switch (source)
        !           178:                {
        !           179:                        case IIR_RX_DATA_READY_INTERRUPT:
        !           180:                                b = inportb (p->uart + RECEIVE_BUFFER_REGISTER);
        !           181:                                if (! FULL(p->inputQueue))
        !           182:                                {
        !           183:                                        ENQUEUE (p->inputQueue, b);
        !           184:                                }
        !           185:                                else
        !           186:                                {
        !           187:                                        p->lineStatus |= LSR_OVERRUN_ERROR;
        !           188:                                        p->statusUpdated = true;
        !           189:                                }
        !           190:                                break;
        !           191: 
        !           192:                        case IIR_TX_HOLDING_REGISTER_INTERRUPT:
        !           193:                                if (! EMPTY(p->outputQueue))
        !           194:                                {
        !           195:                                        DEQUEUE (p->outputQueue, b);
        !           196:                                        outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b);
        !           197:                                }
        !           198:                                break;
        !           199: 
        !           200:                        case IIR_MODEM_STATUS_INTERRUPT:
        !           201:                                p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
        !           202:                                p->statusUpdated = true;
        !           203:                                break;
        !           204: 
        !           205:                        case IIR_LINE_STATUS_INTERRUPT:
        !           206:                                p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER);
        !           207:                                p->statusUpdated = true;
        !           208:                                break;
        !           209:                }
        !           210:                source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07;
        !           211:        }
        !           212:        outportb (0x20, 0x20);
        !           213: }
        !           214: 
        !           215: static void COM1_ISR_8250 (void)
        !           216: {
        !           217:        ISR_8250 (handleToPort[0]);
        !           218: }
        !           219: 
        !           220: static void COM2_ISR_8250 (void)
        !           221: {
        !           222:        ISR_8250 (handleToPort[1]);
        !           223: }
        !           224: 
        !           225: 
        !           226: 
        !           227: static void ISR_16550 (ComPort *p)
        !           228: {
        !           229:        int             count;
        !           230:        byte    source;
        !           231:        byte    b;
        !           232: 
        !           233:        disable();
        !           234:        while((source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07) != 1)
        !           235:        {
        !           236:                switch (source)
        !           237:                {
        !           238:                        case IIR_RX_DATA_READY_INTERRUPT:
        !           239:                                do
        !           240:                                {
        !           241:                                        b = inportb (p->uart + RECEIVE_BUFFER_REGISTER);
        !           242:                                        if (!FULL(p->inputQueue))
        !           243:                                        {
        !           244:                                                ENQUEUE (p->inputQueue, b);
        !           245:                                        }
        !           246:                                        else
        !           247:                                        {
        !           248:                                                p->lineStatus |= LSR_OVERRUN_ERROR;
        !           249:                                                p->statusUpdated = true;
        !           250:                                        }
        !           251:                                } while (inportb (p->uart + LINE_STATUS_REGISTER) & LSR_DATA_READY);
        !           252:                                break;
        !           253: 
        !           254:                        case IIR_TX_HOLDING_REGISTER_INTERRUPT:
        !           255:                                count = 16;
        !           256:                                while ((! EMPTY(p->outputQueue)) && count--)
        !           257:                                {
        !           258:                                        DEQUEUE (p->outputQueue, b);
        !           259:                                        outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b);
        !           260:                                }
        !           261:                                break;
        !           262: 
        !           263:                        case IIR_MODEM_STATUS_INTERRUPT:
        !           264:                                p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
        !           265:                                p->statusUpdated = true;
        !           266:                                break;
        !           267: 
        !           268:                        case IIR_LINE_STATUS_INTERRUPT:
        !           269:                                p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER);
        !           270:                                p->statusUpdated = true;
        !           271:                                break;
        !           272:                }
        !           273:                source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07;
        !           274:        }
        !           275: 
        !           276:        // check for lost IIR_TX_HOLDING_REGISTER_INTERRUPT on 16550a!
        !           277:        if (inportb (p->uart + LINE_STATUS_REGISTER ) & LSR_TRANSMITTER_EMPTY)
        !           278:        {
        !           279:                count = 16;
        !           280:                while ((! EMPTY(p->outputQueue)) && count--)
        !           281:                {
        !           282:                        DEQUEUE (p->outputQueue, b);
        !           283:                        outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b);
        !           284:                }
        !           285:        }
        !           286: 
        !           287:        outportb (0x20, 0x20);
        !           288: }
        !           289: 
        !           290: static void COM1_ISR_16550 (void)
        !           291: {
        !           292:        ISR_16550 (handleToPort[0]);
        !           293: }
        !           294: 
        !           295: static void COM2_ISR_16550 (void)
        !           296: {
        !           297:        ISR_16550 (handleToPort[1]);
        !           298: }
        !           299: 
        !           300: 
        !           301: void TTY_GetComPortConfig (int portNumber, int *port, int *irq, int *baud, qboolean *useModem)
        !           302: {
        !           303:        ComPort *p;
        !           304: 
        !           305:        p = handleToPort[portNumber];
        !           306:        *port = p->uart;
        !           307:        *irq = p->irq;
        !           308:        *baud = 115200 / p->baudBits;
        !           309:        *useModem = p->useModem;
        !           310: }
        !           311: 
        !           312: void TTY_SetComPortConfig (int portNumber, int port, int irq, int baud, qboolean useModem)
        !           313: {
        !           314:        ComPort *p;
        !           315:        float   temp;
        !           316: 
        !           317:        if (useModem)
        !           318:        {
        !           319:                if (baud == 14400)
        !           320:                        baud = 19200;
        !           321:                if (baud == 28800)
        !           322:                        baud = 38400;
        !           323:        }
        !           324: 
        !           325:        p = handleToPort[portNumber];
        !           326:        p->uart = port;
        !           327:        p->irq = irq;
        !           328:        p->baudBits = 115200 / baud;
        !           329:        p->useModem = useModem;
        !           330: 
        !           331:        if (useModem)
        !           332:                temp = 1.0;
        !           333:        else
        !           334:                temp = 0.0;
        !           335: 
        !           336:        Cvar_SetValue ("_config_com_port", (float)port);
        !           337:        Cvar_SetValue ("_config_com_irq", (float)irq);
        !           338:        Cvar_SetValue ("_config_com_baud", (float)baud);
        !           339:        Cvar_SetValue ("_config_com_modem", temp);
        !           340: }
        !           341: 
        !           342: void TTY_GetModemConfig (int portNumber, char *dialType, char *clear, char *init, char *hangup)
        !           343: {
        !           344:        ComPort *p;
        !           345: 
        !           346:        p = handleToPort[portNumber];
        !           347:        *dialType = p->dialType;
        !           348:        Q_strcpy(clear, p->clear);
        !           349:        Q_strcpy(init, p->startup);
        !           350:        Q_strcpy(hangup, p->shutdown);
        !           351: }
        !           352: 
        !           353: void TTY_SetModemConfig (int portNumber, char *dialType, char *clear, char *init, char *hangup)
        !           354: {
        !           355:        ComPort *p;
        !           356: 
        !           357:        p = handleToPort[portNumber];
        !           358:        p->dialType = dialType[0];
        !           359:        Q_strcpy(p->clear, clear);
        !           360:        Q_strcpy(p->startup, init);
        !           361:        Q_strcpy(p->shutdown, hangup);
        !           362: 
        !           363:        p->modemInitialized = false;
        !           364: 
        !           365:        Cvar_Set ("_config_modem_dialtype", dialType);
        !           366:        Cvar_Set ("_config_modem_clear", clear);
        !           367:        Cvar_Set ("_config_modem_init", init);
        !           368:        Cvar_Set ("_config_modem_hangup", hangup);
        !           369: }
        !           370: 
        !           371: 
        !           372: static void ResetComPortConfig (ComPort *p)
        !           373: {
        !           374:        p->useModem = false;
        !           375:        p->uartType = UART_AUTO;
        !           376:        p->uart = ISA_uarts[p->portNumber];
        !           377:        p->irq = ISA_IRQs[p->portNumber];
        !           378:        p->modemStatusIgnore = MSR_CD | MSR_CTS | MSR_DSR;
        !           379:        p->baudBits = 115200 / 57600;
        !           380:        p->lineControl = LCR_DATA_BITS_8 | LCR_STOP_BITS_1 | LCR_PARITY_NONE;
        !           381:        Q_strcpy(p->clear, "ATZ");
        !           382:        Q_strcpy(p->startup, "");
        !           383:        Q_strcpy(p->shutdown, "AT H");
        !           384:        p->modemRang = false;
        !           385:        p->modemConnected = false;
        !           386:        p->statusUpdated = false;
        !           387:        p->outputQueue.head = p->outputQueue.tail = 0;
        !           388:        p->inputQueue.head = p->inputQueue.tail = 0;
        !           389: }
        !           390: 
        !           391: 
        !           392: static void ComPort_Enable(ComPort *p)
        !           393: {
        !           394:        void    (*isr)(void);
        !           395:        int             n;
        !           396:        byte    b;
        !           397: 
        !           398:        if (p->enabled)
        !           399:        {
        !           400:                Con_Printf("Already enabled\n");
        !           401:                return;
        !           402:        }
        !           403: 
        !           404:        // disable all UART interrupts
        !           405:        outportb (p->uart + INTERRUPT_ENABLE_REGISTER, 0);
        !           406: 
        !           407:        // clear out any buffered uncoming data
        !           408:        while((inportb (p->uart + LINE_STATUS_REGISTER)) & LSR_DATA_READY)
        !           409:                inportb (p->uart + RECEIVE_BUFFER_REGISTER);
        !           410: 
        !           411:        // get the current line and modem status
        !           412:        p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
        !           413:        p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER);
        !           414: 
        !           415:        // clear any UART interrupts
        !           416:        do
        !           417:        {
        !           418:                n = inportb (p->uart + INTERRUPT_ID_REGISTER) & 7;
        !           419:                if (n == IIR_RX_DATA_READY_INTERRUPT)
        !           420:                        inportb (p->uart + RECEIVE_BUFFER_REGISTER);
        !           421:        } while (!(n & 1));
        !           422: 
        !           423:        if (p->uartType == UART_AUTO)
        !           424:        {
        !           425:                outportb (p->uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE);
        !           426:                b = inportb (p->uart + INTERRUPT_ID_REGISTER);
        !           427:                if ((b & IIR_FIFO_ENABLED) == IIR_FIFO_ENABLED)
        !           428:                        p->uartType = UART_16550;
        !           429:                else
        !           430:                        p->uartType = UART_8250;
        !           431:        }
        !           432: 
        !           433:        // save the old interrupt handler
        !           434:        _go32_dpmi_get_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeSaveInfo);
        !           435: 
        !           436:        if (p->uartType == UART_8250)
        !           437:        {
        !           438:                outportb (p->uart + FIFO_CONTROL_REGISTER, 0);
        !           439:                if (p == handleToPort[0])
        !           440:                        isr = COM1_ISR_8250;
        !           441:                else
        !           442:                        isr = COM2_ISR_8250;
        !           443:        }
        !           444:        else
        !           445:        {
        !           446:                outportb (p->uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE | FCR_RCVR_FIFO_RESET | FCR_XMIT_FIFO_RESET | FCR_TRIGGER_08);
        !           447:                if (p == handleToPort[0])
        !           448:                        isr = COM1_ISR_16550;
        !           449:                else
        !           450:                        isr = COM2_ISR_16550;
        !           451:        }
        !           452: 
        !           453:        p->protectedModeInfo.pm_offset = (int)isr;
        !           454: 
        !           455:        n = _go32_dpmi_allocate_iret_wrapper(&p->protectedModeInfo);
        !           456:        if (n)
        !           457:        {
        !           458:                Con_Printf("serial: protected mode callback allocation failed\n");
        !           459:                return;
        !           460:        }
        !           461: 
        !           462:        // disable interrupts at the processor
        !           463:        disable();
        !           464: 
        !           465:        // install our interrupt handlers now
        !           466:        _go32_dpmi_set_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeInfo);
        !           467: 
        !           468:        // enable our interrupt at the PIC
        !           469:        outportb (0x21, inportb (0x21) & ~(1<<p->irq));
        !           470: 
        !           471:        // enable interrupts at the processor
        !           472:        enable();
        !           473: 
        !           474:        // enable interrupts at the PIC
        !           475:        outportb (0x20, 0xc2);
        !           476: 
        !           477:        // set baud rate & line control
        !           478:        outportb (p->uart + LINE_CONTROL_REGISTER, LCR_DLAB | p->lineControl);
        !           479:        outportb (p->uart, p->baudBits);
        !           480:        outportb (p->uart + 1, 0);
        !           481:        outportb (p->uart + LINE_CONTROL_REGISTER, p->lineControl);
        !           482: 
        !           483:        // set modem control register & enable uart interrupt generation
        !           484:        outportb(p->uart + MODEM_CONTROL_REGISTER, MCR_OUT2 | MCR_RTS | MCR_DTR);
        !           485: 
        !           486:        // enable the individual interrupts at the uart
        !           487:        outportb (p->uart + INTERRUPT_ENABLE_REGISTER, IER_RX_DATA_READY | IER_TX_HOLDING_REGISTER_EMPTY | IER_LINE_STATUS | IER_MODEM_STATUS);
        !           488: 
        !           489:        p->enabled = true;
        !           490: }
        !           491: 
        !           492: 
        !           493: static void ComPort_Disable(ComPort *p)
        !           494: {
        !           495:        if (!p->enabled)
        !           496:        {
        !           497:                Con_Printf("Already disabled\n");
        !           498:                return;
        !           499:        }
        !           500: 
        !           501:        // disable interrupts at the uart
        !           502:        outportb (p->uart + INTERRUPT_ENABLE_REGISTER, 0);
        !           503: 
        !           504:        // disable our interrupt at the PIC
        !           505:        outportb (0x21, inportb (0x21) | (1<<p->irq));
        !           506: 
        !           507:        // disable interrupts at the processor
        !           508:        disable();
        !           509: 
        !           510:        // restore the old interrupt handler
        !           511:        _go32_dpmi_set_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeSaveInfo);
        !           512:        _go32_dpmi_free_iret_wrapper(&p->protectedModeInfo);
        !           513: 
        !           514:        // enable interrupts at the processor
        !           515:        enable();
        !           516: 
        !           517:        p->enabled = false;
        !           518: }
        !           519: 
        !           520: 
        !           521: static int CheckStatus (ComPort *p)
        !           522: {
        !           523:        int             ret = 0;
        !           524: 
        !           525:        if (p->statusUpdated)
        !           526:        {
        !           527:                p->statusUpdated = false;
        !           528: 
        !           529:                if (p->lineStatus & (LSR_OVERRUN_ERROR | LSR_PARITY_ERROR | LSR_FRAMING_ERROR | LSR_BREAK_DETECT))
        !           530:                {
        !           531:                        if (p->lineStatus & LSR_OVERRUN_ERROR)
        !           532:                                Con_DPrintf ("Serial overrun error\n");
        !           533:                        if (p->lineStatus & LSR_PARITY_ERROR)
        !           534:                                Con_DPrintf ("Serial parity error\n");
        !           535:                        if (p->lineStatus & LSR_FRAMING_ERROR)
        !           536:                                Con_DPrintf ("Serial framing error\n");
        !           537:                        if (p->lineStatus & LSR_BREAK_DETECT)
        !           538:                                Con_DPrintf ("Serial break detect\n");
        !           539:                        ret = ERR_TTY_LINE_STATUS;
        !           540:                }
        !           541: 
        !           542:                if ((p->modemStatus & MODEM_STATUS_MASK) != MODEM_STATUS_MASK)
        !           543:                {
        !           544:                        if (!(p->modemStatus & MSR_CTS))
        !           545:                                Con_Printf ("Serial lost CTS\n");
        !           546:                        if (!(p->modemStatus & MSR_DSR))
        !           547:                                Con_Printf ("Serial lost DSR\n");
        !           548:                        if (!(p->modemStatus & MSR_CD))
        !           549:                                Con_Printf ("Serial lost Carrier\n");
        !           550:                        ret = ERR_TTY_MODEM_STATUS;
        !           551:                }
        !           552:        }
        !           553: 
        !           554:        return ret;
        !           555: }
        !           556: 
        !           557: 
        !           558: static void Modem_Init(ComPort *p)
        !           559: {
        !           560:        double  start;
        !           561:        char    *response;
        !           562: 
        !           563:        Con_Printf ("Initializing modem...\n");
        !           564: 
        !           565:        // write 0 to MCR, wait 1/2 sec, then write the real value back again
        !           566:        // I got this from the guys at head-to-head who say it's necessary.
        !           567:        outportb(p->uart + MODEM_CONTROL_REGISTER, 0);
        !           568:        start = Sys_FloatTime();
        !           569:        while ((Sys_FloatTime() - start) < 0.5)
        !           570:                ;
        !           571:        outportb(p->uart + MODEM_CONTROL_REGISTER, MCR_OUT2 | MCR_RTS | MCR_DTR);
        !           572:        start = Sys_FloatTime();
        !           573:        while ((Sys_FloatTime() - start) < 0.25)
        !           574:                ;
        !           575: 
        !           576:        if (*p->clear)
        !           577:        {
        !           578:                Modem_Command (p, p->clear);
        !           579:                start = Sys_FloatTime();
        !           580:                while(1)
        !           581:                {
        !           582:                        if ((Sys_FloatTime() - start) > 3.0)
        !           583:                        {
        !           584:                                Con_Printf("No response - clear failed\n");
        !           585:                                p->enabled = false;
        !           586:                                goto failed;
        !           587:                        }
        !           588:                        response = Modem_Response(p);
        !           589:                        if (!response)
        !           590:                                continue;
        !           591:                        if (Q_strncmp(response, "OK", 2) == 0)
        !           592:                                break;
        !           593:                        if (Q_strncmp(response, "ERROR", 5) == 0)
        !           594:                        {
        !           595:                                p->enabled = false;
        !           596:                                goto failed;
        !           597:                        }
        !           598:                }
        !           599:        }
        !           600: 
        !           601:        if (*p->startup)
        !           602:        {
        !           603:                Modem_Command (p, p->startup);
        !           604:                start = Sys_FloatTime();
        !           605:                while(1)
        !           606:                {
        !           607:                        if ((Sys_FloatTime() - start) > 3.0)
        !           608:                        {
        !           609:                                Con_Printf("No response - init failed\n");
        !           610:                                p->enabled = false;
        !           611:                                goto failed;
        !           612:                        }
        !           613:                        response = Modem_Response(p);
        !           614:                        if (!response)
        !           615:                                continue;
        !           616:                        if (Q_strncmp(response, "OK", 2) == 0)
        !           617:                                break;
        !           618:                        if (Q_strncmp(response, "ERROR", 5) == 0)
        !           619:                        {
        !           620:                                p->enabled = false;
        !           621:                                goto failed;
        !           622:                        }
        !           623:                }
        !           624:        }
        !           625: 
        !           626:        p->modemInitialized = true;
        !           627:        return;
        !           628: 
        !           629: failed:
        !           630:        if (m_return_onerror)
        !           631:        {
        !           632:                key_dest = key_menu;
        !           633:                m_state = m_return_state;
        !           634:                m_return_onerror = false;
        !           635:                Q_strcpy(m_return_reason, "Initialization Failed");
        !           636:        }
        !           637:        return;
        !           638: }
        !           639: 
        !           640: 
        !           641: void TTY_Enable(int handle)
        !           642: {
        !           643:        ComPort *p;
        !           644: 
        !           645:        p = handleToPort [handle];
        !           646:        if (p->enabled)
        !           647:                return;
        !           648: 
        !           649:        ComPort_Enable(p);
        !           650: 
        !           651:        if (p->useModem && !p->modemInitialized)
        !           652:                Modem_Init (p);
        !           653: }
        !           654: 
        !           655: 
        !           656: int TTY_Open(int serialPortNumber)
        !           657: {
        !           658:        return serialPortNumber;
        !           659: }
        !           660: 
        !           661: 
        !           662: void TTY_Close(int handle)
        !           663: {
        !           664:        ComPort *p;
        !           665:        double          startTime;
        !           666: 
        !           667:        p = handleToPort [handle];
        !           668: 
        !           669:        startTime = Sys_FloatTime();
        !           670:        while ((Sys_FloatTime() - startTime) < 1.0)
        !           671:                if (EMPTY(p->outputQueue))
        !           672:                        break;
        !           673: 
        !           674:        if (p->useModem)
        !           675:        {
        !           676:                if (p->modemConnected)
        !           677:                        Modem_Hangup(p);
        !           678:        }
        !           679: }
        !           680: 
        !           681: 
        !           682: int TTY_ReadByte(int handle)
        !           683: {
        !           684:        int             ret;
        !           685:        ComPort *p;
        !           686: 
        !           687:        p = handleToPort [handle];
        !           688: 
        !           689:        if ((ret = CheckStatus (p)) != 0)
        !           690:                return ret;
        !           691:        
        !           692:        if (EMPTY (p->inputQueue))
        !           693:                return ERR_TTY_NODATA;
        !           694: 
        !           695:        DEQUEUE (p->inputQueue, ret);
        !           696:        return (ret & 0xff);
        !           697: }
        !           698: 
        !           699: 
        !           700: int TTY_WriteByte(int handle, byte data)
        !           701: {
        !           702:        ComPort *p;
        !           703: 
        !           704:        p = handleToPort [handle];
        !           705:        if (FULL(p->outputQueue))
        !           706:                return -1;
        !           707: 
        !           708:        ENQUEUE (p->outputQueue, data);
        !           709:        return 0;
        !           710: }
        !           711: 
        !           712: 
        !           713: void TTY_Flush(int handle)
        !           714: {
        !           715:        byte b;
        !           716:        ComPort *p;
        !           717: 
        !           718:        p = handleToPort [handle];
        !           719: 
        !           720:        if (inportb (p->uart + LINE_STATUS_REGISTER ) & LSR_TRANSMITTER_EMPTY)
        !           721:        {
        !           722:                DEQUEUE (p->outputQueue, b);
        !           723:                outportb(p->uart, b);
        !           724:        }
        !           725: }
        !           726: 
        !           727: 
        !           728: int TTY_Connect(int handle, char *host)
        !           729: {
        !           730:        double  start;
        !           731:        ComPort *p;
        !           732:        char    *response = NULL;
        !           733:        keydest_t       save_key_dest;
        !           734:        byte    dialstring[64];
        !           735:        byte    b;
        !           736: 
        !           737:        p = handleToPort[handle];
        !           738: 
        !           739:        if ((p->modemStatus & MODEM_STATUS_MASK) != MODEM_STATUS_MASK)
        !           740:        {
        !           741:                Con_Printf ("Serial: line not ready (");
        !           742:                if ((p->modemStatus & MSR_CTS) == 0)
        !           743:                        Con_Printf(" CTS");
        !           744:                if ((p->modemStatus & MSR_DSR) == 0)
        !           745:                        Con_Printf(" DSR");
        !           746:                if ((p->modemStatus & MSR_CD) == 0)
        !           747:                        Con_Printf(" CD");
        !           748:                Con_Printf(" )");
        !           749:                return -1;
        !           750:        }
        !           751: 
        !           752:        // discard any scraps in the input buffer
        !           753:        while (! EMPTY (p->inputQueue))
        !           754:                DEQUEUE (p->inputQueue, b);
        !           755: 
        !           756:        CheckStatus (p);
        !           757: 
        !           758:        if (p->useModem)
        !           759:        {
        !           760:                save_key_dest = key_dest;
        !           761:                key_dest = key_console;
        !           762:                key_count = -2;
        !           763: 
        !           764:                Con_Printf ("Dialing...\n");
        !           765:                sprintf(dialstring, "AT D%c %s\r", p->dialType, host);
        !           766:                Modem_Command (p, dialstring);
        !           767:                start = Sys_FloatTime();
        !           768:                while(1)
        !           769:                {
        !           770:                        if ((Sys_FloatTime() - start) > 60.0)
        !           771:                        {
        !           772:                                Con_Printf("Dialing failure!\n");
        !           773:                                break;
        !           774:                        }
        !           775: 
        !           776:                        Sys_SendKeyEvents ();
        !           777:                        if (key_count == 0)
        !           778:                        {
        !           779:                                if (key_lastpress != K_ESCAPE)
        !           780:                                {
        !           781:                                        key_count = -2;
        !           782:                                        continue;
        !           783:                                }
        !           784:                                Con_Printf("Aborting...\n");
        !           785:                                while ((Sys_FloatTime() - start) < 5.0)
        !           786:                                        ;
        !           787:                                disable();
        !           788:                                p->outputQueue.head = p->outputQueue.tail = 0;
        !           789:                                p->inputQueue.head = p->inputQueue.tail = 0;
        !           790:                                outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) & ~MCR_DTR);
        !           791:                                enable();
        !           792:                                start = Sys_FloatTime();
        !           793:                                while ((Sys_FloatTime() - start) < 0.75)
        !           794:                                        ;
        !           795:                                outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) | MCR_DTR);
        !           796:                                response = "Aborted";
        !           797:                                break;
        !           798:                        }
        !           799: 
        !           800:                        response = Modem_Response(p);
        !           801:                        if (!response)
        !           802:                                continue;
        !           803:                        if (Q_strncmp(response, "CONNECT", 7) == 0)
        !           804:                        {
        !           805:                                disable();
        !           806:                                p->modemRang = true;
        !           807:                                p->modemConnected = true;
        !           808:                                p->outputQueue.head = p->outputQueue.tail = 0;
        !           809:                                p->inputQueue.head = p->inputQueue.tail = 0;
        !           810:                                enable();
        !           811:                                key_dest = save_key_dest;
        !           812:                                key_count = 0;
        !           813:                                m_return_onerror = false;
        !           814:                                return 0;
        !           815:                        }
        !           816:                        if (Q_strncmp(response, "NO CARRIER", 10) == 0)
        !           817:                                break;
        !           818:                        if (Q_strncmp(response, "NO DIALTONE", 11) == 0)
        !           819:                                break;
        !           820:                        if (Q_strncmp(response, "NO DIAL TONE", 12) == 0)
        !           821:                                break;
        !           822:                        if (Q_strncmp(response, "NO ANSWER", 9) == 0)
        !           823:                                break;
        !           824:                        if (Q_strncmp(response, "BUSY", 4) == 0)
        !           825:                                break;
        !           826:                        if (Q_strncmp(response, "ERROR", 5) == 0)
        !           827:                                break;
        !           828:                }
        !           829:                key_dest = save_key_dest;
        !           830:                key_count = 0;
        !           831:                if (m_return_onerror)
        !           832:                {
        !           833:                        key_dest = key_menu;
        !           834:                        m_state = m_return_state;
        !           835:                        m_return_onerror = false;
        !           836:                        Q_strncpy(m_return_reason, response, 31);
        !           837:                }
        !           838:                return -1;
        !           839:        }
        !           840:        m_return_onerror = false;
        !           841:        return 0;
        !           842: }
        !           843: 
        !           844: 
        !           845: void TTY_Disconnect(int handle)
        !           846: {
        !           847:        ComPort *p;
        !           848: 
        !           849:        p = handleToPort[handle];
        !           850: 
        !           851:        if (p->useModem && p->modemConnected)
        !           852:                Modem_Hangup(p);
        !           853: }
        !           854: 
        !           855: 
        !           856: qboolean TTY_CheckForConnection(int handle)
        !           857: {
        !           858:        ComPort *p;
        !           859: 
        !           860:        p = handleToPort[handle];
        !           861: 
        !           862:        CheckStatus (p);
        !           863: 
        !           864:        if (p->useModem)
        !           865:        {
        !           866:                if (!p->modemRang)
        !           867:                {
        !           868:                        if (!Modem_Response(p))
        !           869:                                return false;
        !           870: 
        !           871:                        if (Q_strncmp(p->buffer, "RING", 4) == 0)
        !           872:                        {
        !           873:                                Modem_Command (p, "ATA");
        !           874:                                p->modemRang = true;
        !           875:                                p->timestamp = net_time;
        !           876:                        }
        !           877:                        return false;
        !           878:                }
        !           879:                if (!p->modemConnected)
        !           880:                {
        !           881:                        if ((net_time - p->timestamp) > 35.0)
        !           882:                        {
        !           883:                                Con_Printf("Unable to establish modem connection\n");
        !           884:                                p->modemRang = false;
        !           885:                                return false;
        !           886:                        }
        !           887: 
        !           888:                        if (!Modem_Response(p))
        !           889:                                return false;
        !           890: 
        !           891:                        if (Q_strncmp (p->buffer, "CONNECT", 7) != 0)
        !           892:                                return false;
        !           893: 
        !           894:                        disable();
        !           895:                        p->modemConnected = true;
        !           896:                        p->outputQueue.head = p->outputQueue.tail = 0;
        !           897:                        p->inputQueue.head = p->inputQueue.tail = 0;
        !           898:                        enable();
        !           899:                        Con_Printf("Modem Connect\n");
        !           900:                        return true;
        !           901:                }
        !           902:                return true;
        !           903:        }
        !           904: 
        !           905:        // direct connect case
        !           906:        if (EMPTY (p->inputQueue))
        !           907:                return false;
        !           908:        return true;
        !           909: }
        !           910: 
        !           911: 
        !           912: qboolean TTY_IsEnabled(int serialPortNumber)
        !           913: {
        !           914:        return handleToPort[serialPortNumber]->enabled;
        !           915: }
        !           916: 
        !           917: 
        !           918: qboolean TTY_IsModem(int serialPortNumber)
        !           919: {
        !           920:        return handleToPort[serialPortNumber]->useModem;
        !           921: }
        !           922: 
        !           923: 
        !           924: qboolean TTY_OutputQueueIsEmpty(int handle)
        !           925: {
        !           926:        return EMPTY(handleToPort[handle]->outputQueue);
        !           927: }
        !           928: 
        !           929: 
        !           930: void Com_f (void)
        !           931: {
        !           932:        ComPort *p;
        !           933:        int             portNumber;
        !           934:        int             i;
        !           935:        int             n;
        !           936: 
        !           937:        // first, determine which port they're messing with
        !           938:        portNumber = Q_atoi(Cmd_Argv (0) + 3) - 1;
        !           939:        if (portNumber > 1)
        !           940:                return;
        !           941:        p = handleToPort[portNumber];
        !           942: 
        !           943:        if (Cmd_Argc() == 1)
        !           944:        {
        !           945:                Con_Printf("Settings for COM%i\n", portNumber + 1);
        !           946:                Con_Printf("enabled:   %s\n", p->enabled ? "true" : "false");
        !           947:                Con_Printf("uart:      ");
        !           948:                if (p->uartType == UART_AUTO)
        !           949:                        Con_Printf("auto\n");
        !           950:                else if (p->uartType == UART_8250)
        !           951:                        Con_Printf("8250\n");
        !           952:                else
        !           953:                        Con_Printf("16550\n");
        !           954:                Con_Printf("port:      %x\n", p->uart);
        !           955:                Con_Printf("irq:       %i\n", p->irq);
        !           956:                Con_Printf("baud:      %i\n", 115200 / p->baudBits);    
        !           957:                Con_Printf("CTS:       %s\n", (p->modemStatusIgnore & MSR_CTS) ? "ignored" : "honored");
        !           958:                Con_Printf("DSR:       %s\n", (p->modemStatusIgnore & MSR_DSR) ? "ignored" : "honored");
        !           959:                Con_Printf("CD:        %s\n", (p->modemStatusIgnore & MSR_CD) ? "ignored" : "honored");
        !           960:                if (p->useModem)
        !           961:                {
        !           962:                        Con_Printf("type:      Modem\n");
        !           963:                        Con_Printf("clear:     %s\n", p->clear);
        !           964:                        Con_Printf("startup:   %s\n", p->startup);
        !           965:                        Con_Printf("shutdown:  %s\n", p->shutdown);
        !           966:                }
        !           967:                else
        !           968:                        Con_Printf("type:      Direct connect\n");
        !           969: 
        !           970:                return;
        !           971:        }
        !           972: 
        !           973: 
        !           974:        if (Cmd_CheckParm ("disable"))
        !           975:        {
        !           976:                if (p->enabled)
        !           977:                        ComPort_Disable(p);
        !           978:                p->modemInitialized = false;
        !           979:                return;
        !           980:        }
        !           981: 
        !           982:        if (Cmd_CheckParm ("reset"))
        !           983:        {
        !           984:                ComPort_Disable(p);
        !           985:                ResetComPortConfig (p);
        !           986:                return;
        !           987:        }
        !           988: 
        !           989:        if ((i = Cmd_CheckParm ("port")) != 0)
        !           990:        {
        !           991:                if (p->enabled)
        !           992:                        {
        !           993:                                Con_Printf("COM port must be disabled to change port\n");
        !           994:                                return;
        !           995:                        }
        !           996:                p->uart = Q_atoi (Cmd_Argv (i+1));
        !           997:        }
        !           998: 
        !           999:        if ((i = Cmd_CheckParm ("irq")) != 0)
        !          1000:        {
        !          1001:                if (p->enabled)
        !          1002:                        {
        !          1003:                                Con_Printf("COM port must be disabled to change irq\n");
        !          1004:                                return;
        !          1005:                        }
        !          1006:                p->irq = Q_atoi (Cmd_Argv (i+1));
        !          1007:        }
        !          1008: 
        !          1009:        if ((i = Cmd_CheckParm ("baud")) != 0)
        !          1010:        {
        !          1011:                if (p->enabled)
        !          1012:                        {
        !          1013:                                Con_Printf("COM port must be disabled to change baud\n");
        !          1014:                                return;
        !          1015:                        }
        !          1016:                n = Q_atoi (Cmd_Argv (i+1));
        !          1017:                if (n == 0)
        !          1018:                        Con_Printf("Invalid baud rate specified\n");
        !          1019:                else
        !          1020:                        p->baudBits = 115200 / n;
        !          1021:        }
        !          1022: 
        !          1023:        if (Cmd_CheckParm ("8250"))
        !          1024:        {
        !          1025:                if (p->enabled)
        !          1026:                        {
        !          1027:                                Con_Printf("COM port must be disabled to change uart\n");
        !          1028:                                return;
        !          1029:                        }
        !          1030:                p->uartType = UART_8250;
        !          1031:                }
        !          1032:        if (Cmd_CheckParm ("16550"))
        !          1033:        {
        !          1034:                if (p->enabled)
        !          1035:                        {
        !          1036:                                Con_Printf("COM port must be disabled to change uart\n");
        !          1037:                                return;
        !          1038:                        }
        !          1039:                p->uartType = UART_16550;
        !          1040:        }
        !          1041:        if (Cmd_CheckParm ("auto"))
        !          1042:        {
        !          1043:                if (p->enabled)
        !          1044:                        {
        !          1045:                                Con_Printf("COM port must be disabled to change uart\n");
        !          1046:                                return;
        !          1047:                        }
        !          1048:                p->uartType = UART_AUTO;
        !          1049:        }
        !          1050: 
        !          1051:        if (Cmd_CheckParm ("pulse"))
        !          1052:                p->dialType = 'P';
        !          1053:        if (Cmd_CheckParm ("tone"))
        !          1054:                p->dialType = 'T';
        !          1055: 
        !          1056:        if (Cmd_CheckParm ("direct"))
        !          1057:                p->useModem = false;
        !          1058:        if (Cmd_CheckParm ("modem"))
        !          1059:                p->useModem = true;
        !          1060: 
        !          1061:        if ((i = Cmd_CheckParm ("clear")) != 0)
        !          1062:        {
        !          1063:                Q_strncpy (p->clear, Cmd_Argv (i+1), 16);
        !          1064:        }
        !          1065: 
        !          1066:        if ((i = Cmd_CheckParm ("startup")) != 0)
        !          1067:        {
        !          1068:                Q_strncpy (p->startup, Cmd_Argv (i+1), 32);
        !          1069:                p->modemInitialized = false;
        !          1070:        }
        !          1071: 
        !          1072:        if ((i = Cmd_CheckParm ("shutdown")) != 0)
        !          1073:        {
        !          1074:                Q_strncpy (p->shutdown, Cmd_Argv (i+1), 16);
        !          1075:        }
        !          1076: 
        !          1077:        if (Cmd_CheckParm ("-cts"))
        !          1078:        {
        !          1079:                p->modemStatusIgnore |= MSR_CTS;
        !          1080:                p->modemStatus |= MSR_CTS;
        !          1081:        }
        !          1082: 
        !          1083:        if (Cmd_CheckParm ("+cts"))
        !          1084:        {
        !          1085:                p->modemStatusIgnore &= (~MSR_CTS);
        !          1086:                p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
        !          1087:        }
        !          1088: 
        !          1089:        if (Cmd_CheckParm ("-dsr"))
        !          1090:        {
        !          1091:                p->modemStatusIgnore |= MSR_DSR;
        !          1092:                p->modemStatus |= MSR_DSR;
        !          1093:        }
        !          1094: 
        !          1095:        if (Cmd_CheckParm ("+dsr"))
        !          1096:        {
        !          1097:                p->modemStatusIgnore &= (~MSR_DSR);
        !          1098:                p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
        !          1099:        }
        !          1100: 
        !          1101:        if (Cmd_CheckParm ("-cd"))
        !          1102:        {
        !          1103:                p->modemStatusIgnore |= MSR_CD;
        !          1104:                p->modemStatus |= MSR_CD;
        !          1105:        }
        !          1106: 
        !          1107:        if (Cmd_CheckParm ("+cd"))
        !          1108:        {
        !          1109:                p->modemStatusIgnore &= (~MSR_CD);
        !          1110:                p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore;
        !          1111:        }
        !          1112: 
        !          1113:        if (Cmd_CheckParm ("enable"))
        !          1114:        {
        !          1115:                if (!p->enabled)
        !          1116:                        ComPort_Enable(p);
        !          1117:                if (p->useModem && !p->modemInitialized)
        !          1118:                        Modem_Init (p);
        !          1119:        }
        !          1120: }
        !          1121: 
        !          1122: 
        !          1123: int TTY_Init(void)
        !          1124: {
        !          1125:        int             n;
        !          1126:        ComPort *p;
        !          1127: 
        !          1128:        for (n = 0; n < NUM_COM_PORTS; n++)
        !          1129:        {
        !          1130:                p = (ComPort *)Hunk_AllocName(sizeof(ComPort), "comport");
        !          1131:                if (p == NULL)
        !          1132:                        Sys_Error("Hunk alloc failed for com port\n");
        !          1133:                p->next = portList;
        !          1134:                portList = p;
        !          1135:                handleToPort[n] = p;
        !          1136:                p->portNumber = n;
        !          1137:                p->dialType = 'T';
        !          1138:                sprintf(p->name, "com%u", n+1);
        !          1139:                Cmd_AddCommand (p->name, Com_f);
        !          1140:                ResetComPortConfig (p);
        !          1141:        }
        !          1142: 
        !          1143:        GetComPortConfig = TTY_GetComPortConfig;
        !          1144:        SetComPortConfig = TTY_SetComPortConfig;
        !          1145:        GetModemConfig = TTY_GetModemConfig;
        !          1146:        SetModemConfig = TTY_SetModemConfig;
        !          1147: 
        !          1148:        return 0;
        !          1149: }
        !          1150: 
        !          1151: 
        !          1152: void TTY_Shutdown(void)
        !          1153: {
        !          1154:        int             n;
        !          1155:        ComPort *p;
        !          1156: 
        !          1157:        for (n = 0; n < NUM_COM_PORTS; n++)
        !          1158:        {
        !          1159:                p = handleToPort[n];
        !          1160:                if (p->enabled)
        !          1161:                {
        !          1162:                        while (p->modemConnected)
        !          1163:                                NET_Poll();
        !          1164:                        ComPort_Disable (p);
        !          1165:                }
        !          1166:        }
        !          1167: }
        !          1168: 
        !          1169: 
        !          1170: static int Modem_Command(ComPort *p, char *commandString)
        !          1171: {
        !          1172:        byte    b;
        !          1173: 
        !          1174:        if (CheckStatus (p))
        !          1175:                return -1;
        !          1176: 
        !          1177:        disable();
        !          1178:        p->outputQueue.head = p->outputQueue.tail = 0;
        !          1179:        p->inputQueue.head = p->inputQueue.tail = 0;
        !          1180:        enable();
        !          1181:        p->bufferUsed = 0;
        !          1182: 
        !          1183:        while (*commandString)
        !          1184:                ENQUEUE (p->outputQueue, *commandString++);
        !          1185:        ENQUEUE (p->outputQueue, '\r');
        !          1186: 
        !          1187:        // get the transmit rolling
        !          1188:        DEQUEUE (p->outputQueue, b);
        !          1189:        outportb(p->uart, b);
        !          1190: 
        !          1191:        return 0;
        !          1192: }
        !          1193: 
        !          1194: 
        !          1195: static char *Modem_Response(ComPort *p)
        !          1196: {
        !          1197:        byte    b;
        !          1198: 
        !          1199:        if (CheckStatus (p))
        !          1200:                return NULL;
        !          1201: 
        !          1202:        while (! EMPTY(p->inputQueue))
        !          1203:        {
        !          1204:                DEQUEUE (p->inputQueue, b);
        !          1205: 
        !          1206:                if (p->bufferUsed == (sizeof(p->buffer) - 1))
        !          1207:                        b = '\r';
        !          1208: 
        !          1209:                if (b == '\r' && p->bufferUsed)
        !          1210:                {
        !          1211:                        p->buffer[p->bufferUsed] = 0;
        !          1212:                        Con_Printf("%s\n", p->buffer);
        !          1213:                        SCR_UpdateScreen ();
        !          1214:                        p->bufferUsed = 0;
        !          1215:                        return p->buffer;
        !          1216:                }
        !          1217: 
        !          1218:                if (b < ' ' || b > 'z')
        !          1219:                        continue;
        !          1220:                p->buffer[p->bufferUsed] = b;
        !          1221:                p->bufferUsed++;
        !          1222:        }
        !          1223: 
        !          1224:        return NULL;
        !          1225: }
        !          1226: 
        !          1227: 
        !          1228: static void Modem_Hangup2(ComPort *p);
        !          1229: static void Modem_Hangup3(ComPort *p);
        !          1230: static void Modem_Hangup4(ComPort *p);
        !          1231: 
        !          1232: static void Modem_Hangup(ComPort *p)
        !          1233: {
        !          1234:        Con_Printf("Hanging up modem...\n");
        !          1235:        disable();
        !          1236:        p->modemRang = false;
        !          1237:        p->outputQueue.head = p->outputQueue.tail = 0;
        !          1238:        p->inputQueue.head = p->inputQueue.tail = 0;
        !          1239:        outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) & ~MCR_DTR);
        !          1240:        enable();
        !          1241:        p->poll.procedure = Modem_Hangup2;
        !          1242:        p->poll.arg = p;
        !          1243:        SchedulePollProcedure(&p->poll, 1.5);
        !          1244: }
        !          1245: 
        !          1246: static void Modem_Hangup2(ComPort *p)
        !          1247: {
        !          1248:        outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) | MCR_DTR);
        !          1249:        Modem_Command(p, "+++");
        !          1250:        p->poll.procedure = Modem_Hangup3;
        !          1251:        SchedulePollProcedure(&p->poll, 1.5);
        !          1252: }
        !          1253: 
        !          1254: static void Modem_Hangup3(ComPort *p)
        !          1255: {
        !          1256:        Modem_Command(p, p->shutdown);
        !          1257:        p->poll.procedure = Modem_Hangup4;
        !          1258:        SchedulePollProcedure(&p->poll, 1.5);
        !          1259: }
        !          1260: 
        !          1261: static void Modem_Hangup4(ComPort *p)
        !          1262: {
        !          1263:        Modem_Response(p);
        !          1264:        Con_Printf("Hangup complete\n");
        !          1265:        p->modemConnected = false;
        !          1266: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.