// This is the main module of a terminal emulator program // to replace PCPLUS for in-house test applications. // compiler: Borland 3.1, DOS real mode // author: Timothy Fox #include <string.h> #include <conio.h> #include <stdlib.h> #include <dir.h> #include <dos.h> #include "typedefs.h" #include "abcconst.h" #include "commutil.h" #include "abcscrn.h" #include "abckbd.h" #include "abctabs.h" #include "tsio.h" #include "dostimer.h" #include "flashdta.h" #include "jultime.h" #include "mmx_info.h" #pragma option -r- static BOOL DONE = FALSE, hooked = FALSE; void end_program(void) { // TO DO: put up a dialog window // Ask the user to confirm the EXIT command DONE = TRUE; } static void pause(UINT ticks) { run_timer(pause_timer, ticks); while (!timer_done(pause_timer)) { } } static int mm_done; static void fkeyproc(void) { switch (getch()) { case 0x3b: // F1 - help cputs("\n"); cputs("Modem Manager commands:\n"); cputs(" F1 - Help\n"); cputs(" F2 - Copy non-volatile memory to disk\n"); cputs(" F3 - Copy disk to non-volatile memory\n"); cputs(" F4 - Copy flash memory to disk\n"); cputs(" F5 - Copy disk to flash memory\n"); cputs("\n"); break; case 0x3c: // F2 - copy non-volatile memory to disk read_nvram_data(); if (nvram_loaded()) { if ((fp = fopen("NVRAM.DAT", "wb")) == NULL) { cputs("Failed to open NVRAM.DAT\n"); } else { cputs("Write non-volatile memory to disk\n"); fwrite(nvram_data, 0x1800, 1, fp); fclose(fp); cputs("Ready\n"); } } break; case 0x3d: // F3 - Copy disk to non-volatile memory cputs("Read non-volatile data from disk\n"); if ((fp = fopen("NVRAM.DAT", "rb")) == NULL) { cputs("Failed to open NVRAM.DAT\n"); } else { load_nv_file(); write_nvram_data(); } break; case 0x3e: // F4 - Copy flash memory to disk recv_flash_data(); if (flash_loaded()) { save_flash_file(); } break; case 0x3f: // F5 - Copy disk to flash memory load_flash_file(current_ID(), current_image_type()); if (flash_loaded()) { xmit_flash_data(); } break; } } static void keyproc(void) { if (0 == kbhit()) return; switch (getch()) { case 0: // function keys fkeyproc(); break; case ESC: mm_done = 1; break; default: COM_OUT(c); } } static void process_mm (void) { #define MAXSHUFFLE 16 #define IDLE_LIMIT 30 // seconds ULONG jul_start, jul_now; mm_done = 0; send_command("READY\r","",0); jul_start = julian_now(); while (!mm_done) { jul_now = julian_now(); if ((jul_now - jul_start) > IDLE_LIMIT) { cputs("\nController idle time exceeded. Abandoning update..."); return; } if (_shuffle()) jul_start = julian_now(); keyproc(); // "\x1B[" is the ANSI terminal escape marker if (shuffle_contains("\x1b[")) return; if (shuffle_contains("DEFINE_BIN\r")) { recv_flash_data() ; jul_start = julian_now(); } if (shuffle_contains("DEFINE_ID\r")) { recv_device_ID() ; jul_start = julian_now(); } } // while !mm_done return; } int main (int _argc, char *_argv[]) { UINT portx, rxc; char drive[MAXDRIVE]; char dir[MAXDIR]; char file[MAXFILE]; char ext[MAXEXT]; if (_argc > 1) { portx = atoi(_argv[1]); if ((portx < 1) || (portx > 2)) { cputs("\r\n The COM port you specify must be either '1' or '2'."); cputs("\r\n You asked for port '"); cputs(_argv[1]); cputs("'.\n"); return 0; } } else { fnsplit(_argv[0],drive,dir,file,ext); cputs("\r\nWhen you start this program, you must specify"); cputs("\r\nthe communication port ('1' or '2') to use."); cputs("\r\n\nFor example, "); cputs(file); cputs(" 1"); cputs("\r\n\nconnects to the Test Rack via COM1: \n"); return 0; } portx--; setup_comport(irqnumbr[portx], baseaddr[portx]); set_COMPARMS(0x03); // "8N1" SET_BAUD_RATE(12); // 9600 baud INSTALL_RTC_ISR(); hooked = TRUE; setup_comport(irqnumbr[portx], baseaddr[portx]); pause(10); teardown_comport(); pause(10); setup_comport(irqnumbr[portx], baseaddr[portx]); init_vt_scrn(); refresh_ANSI_stats(); textattr((BLUE << 4) | LIGHTGRAY); erase_all(); while (host_rx_count()) COM_IN(); // eat any burst of chars from startup cputs("\nABC Terminal ready "); if (!DSR_STATUS()) cputs("\r\n\n waiting for DSR ... "); do { if (host_rx_count()) break; keyboard(); if (DONE) break; } while (!DSR_STATUS()); cputs("\r\n\n"); do { if (host_rx_count()) { rxc = (COM_IN()); if (rxc == ENQ) { COM_OUT(ACK); // clear the screen, and wait for rx activity to stop clrscr(); run_timer(COM_timer, 50); while (!timer_done(COM_timer)) ; cputs("\r\n\n Update server active ...\r\n"); if (setup_flashbuf()) { process_mm(); } // wait for tx queue to be empty while (host_tx_count()) ; run_timer(COM_timer, 30); while (!timer_done(COM_timer)) ; } else { handle_rx(rxc); } } keyboard(); } while (!DONE); clrscr(); return 0; } #ifdef __cplusplus #define __CPPARGS ... #else #define __CPPARGS #endif #define CTRL_C 0x23 void interrupt (* old_ctrl_C) (__CPPARGS); void leave_abc(void) { setvect(CTRL_C, old_ctrl_C); if (hooked) { teardown_comport(); REMOVE_RTC_ISR(); hooked = FALSE; } } void interrupt ctrl_C(__CPPARGS) { leave_abc(); // restore all the hooked interrupts clrscr(); _exit(1); } void init_abc(void) { old_ctrl_C = getvect(CTRL_C); // save the old ctrl-C vector setvect(CTRL_C, ctrl_C); } #pragma startup init_abc #pragma exit leave_abc