|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.