Annotation of quake1/net_comx.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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