#include "ttem_endian_port.h" struct termio termio_struct1, termio_struct2; int ch_status_flag1, ch_status_flag2; int shmid, target_pid; char *shm_addr; CSR_TYPE *csr; void sigfun(int sig) { int i,j,k; shmctl(shmid, IPC_RMID, 0); ioctl(DEVCONIN, TCSETA, &termio_struct1); fcntl(DEVCONIN, F_SETFL, ch_status_flag1); printf("\n\nTTY EMULATOR DRIVER GOING DOWN ON SIGNAL %d \n\n", sig); kill(target_pid, SIGTERM); exit(sig); } int main(int argc, char *argv[]) { struct sigaction new; sigset_t mask_sigs; int i,j,k, nsigs; int buf_used, high_watermark, low_watermark; int in,out,xmtr_off; char inbuf[INBUFSIZE],inchar; int sigs[] = {SIGHUP,SIGINT,SIGQUIT, SIGSEGV, SIGBUS, SIGTERM, SIGXFSZ}; nsigs = sizeof(sigs)/sizeof(int); target_pid = atoi(argv[1]); in=out=0; buf_used=0; xmtr_off = 1; /* high_watermark = HIGHWTRMRK; */ /* low_watermark = LOWWTRMRK; */ printf("\n terminal emulator starting\n"); sigemptyset(&mask_sigs); for(i=0; i< nsigs; i++) sigaddset(&mask_sigs, sigs[i]); for(i=0; i< nsigs; i++){ new.sa_handler = sigfun; new.sa_mask = mask_sigs; new.sa_flags = SA_RESTART; if(sigaction(sigs[i], &new, NULL) == -1){ perror("can't set signals: "); exit(1); } } ioctl(DEVCONIN, TCGETA, &termio_struct1); termio_struct2 = termio_struct1; ch_status_flag1 = fcntl(DEVCONIN, F_GETFL, 0); ch_status_flag2 = ch_status_flag1; termio_struct2.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOK); termio_struct2.c_iflag &= ~(ICRNL | ISTRIP); // termio_struct2.c_oflag &= ~OPOST; termio_struct2.c_cc[4] = 1; termio_struct2.c_cc[5] = 1; if(ioctl(DEVCONIN, TCSETA, &termio_struct2) == -1){ perror("ioctl tcset1 error"); exit(1); } ch_status_flag2 |= O_NONBLOCK; if(fcntl(DEVCONIN, F_SETFL, ch_status_flag2) == -1){ perror("fcntl f_setfl1 error"); exit(1); } if((shmid = shmget(SHKEY, 4096, 0)) == -1){ perror("shmget error"); sigfun( -1 ); } if((shm_addr = shmat(shmid, 0, 0)) == (char *)-1){ perror("shmat error"); sigfun( -1 ); } csr = (CSR_TYPE *)shm_addr; while(1){ if(buf_used < (INBUFSIZE - 1)){ switch(read(DEVCONIN, &inchar, 1)){ case -1: if(errno == EWOULDBLOCK | errno == EAGAIN){ break; }else{ perror("read error"); sigfun( -1 ); } case 0: perror("read at EOF"); sigfun( -1 ); case 1: if(buf_used < (INBUFSIZE - 1)){ inbuf[in] = inchar; in = (in + 1)%INBUFSIZE; ++buf_used; } if(inchar == '\r' && buf_used < (INBUFSIZE - 1)){ inbuf[in] = '\n'; in = (in + 1)%INBUFSIZE; ++buf_used; } break; default: perror("unknown read return"); sigfun( -1 ); } } if(buf_used != 0 && csr->rcsr.rcsr_bit.done == 0){ csr->rbuf.RBUF = inbuf[out]; out = (out + 1)%INBUFSIZE; --buf_used; csr->rcsr.rcsr_bit.done = 1; // if interrupts are enabled send an interrupt if(csr->rcsr.rcsr_bit.int_enbl == 1){ if(kill(target_pid,SIGUSR1) == -1){ perror("signal recv error"); sigfun( -1 ); } } } // if transmitter is asking to wake up if(xmtr_off && csr->xcsr.xcsr_bit.int_enbl == 1 && csr->xcsr.xcsr_bit.done == 0){ // wake up quiesced transmitter if(kill(target_pid,SIGUSR2) == -1){ perror("signal xmit error"); sigfun( -1 ); } xmtr_off = 0; } // if transmitter has a character for the screen if(csr->xcsr.xcsr_bit.done == 1){ if(write(DEVCONOUT, &(csr->xbuf.XBUF), 1) == -1){ perror("write to console error"); sigfun( -1 ); } csr->xcsr.xcsr_bit.done = 0; if(csr->xbuf.xbuf_bit.byte == 'Q')sigfun( -1 ); if(csr->xcsr.xcsr_bit.int_enbl == 1){ // if interrupts are enabled send an interrupt if(kill(target_pid,SIGUSR2) == -1){ perror("signal xmit error"); sigfun( -1 ); } } } if(csr->xcsr.xcsr_bit.int_enbl == 0)xmtr_off = 1; } }