OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.26/] [sim/] [serial.c] - Diff between revs 243 and 246

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 243 Rev 246
Line 1... Line 1...
/*
/*
 * term.c -- terminal simulation
 * serial.c -- serial line simulation
 */
 */
 
 
 
 
#ifdef __linux__
#ifdef __linux__
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE
Line 22... Line 22...
#include "console.h"
#include "console.h"
#include "error.h"
#include "error.h"
#include "except.h"
#include "except.h"
#include "cpu.h"
#include "cpu.h"
#include "timer.h"
#include "timer.h"
#include "term.h"
#include "serial.h"
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
Line 41... Line 41...
  Word rcvrData;
  Word rcvrData;
  int rcvrIRQ;
  int rcvrIRQ;
  Word xmtrCtrl;
  Word xmtrCtrl;
  Word xmtrData;
  Word xmtrData;
  int xmtrIRQ;
  int xmtrIRQ;
} Terminal;
} Serial;
 
 
 
 
static Terminal terminals[MAX_NTERMS];
static Serial serials[MAX_NSERIALS];
static int numTerminals;
static int nSerials;
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
static void rcvrCallback(int dev) {
static void rcvrCallback(int dev) {
  int c;
  int c;
 
 
  if (debug) {
  if (debug) {
    cPrintf("\n**** TERM RCVR CALLBACK ****\n");
    cPrintf("\n**** SERIAL RCVR CALLBACK ****\n");
  }
  }
  timerStart(TERM_RCVR_USEC, rcvrCallback, dev);
  timerStart(SERIAL_RCVR_USEC, rcvrCallback, dev);
  c = fgetc(terminals[dev].in);
  c = fgetc(serials[dev].in);
  if (c == EOF) {
  if (c == EOF) {
    /* no character typed */
    /* no character typed */
    return;
    return;
  }
  }
  /* any character typed */
  /* any character typed */
  terminals[dev].rcvrData = c & 0xFF;
  serials[dev].rcvrData = c & 0xFF;
  terminals[dev].rcvrCtrl |= TERM_RCVR_RDY;
  serials[dev].rcvrCtrl |= SERIAL_RCVR_RDY;
  if (terminals[dev].rcvrCtrl & TERM_RCVR_IEN) {
  if (serials[dev].rcvrCtrl & SERIAL_RCVR_IEN) {
    /* raise terminal rcvr interrupt */
    /* raise serial line rcvr interrupt */
    cpuSetInterrupt(terminals[dev].rcvrIRQ);
    cpuSetInterrupt(serials[dev].rcvrIRQ);
  }
  }
}
}
 
 
 
 
static void xmtrCallback(int dev) {
static void xmtrCallback(int dev) {
  if (debug) {
  if (debug) {
    cPrintf("\n**** TERM XMTR CALLBACK ****\n");
    cPrintf("\n**** SERIAL XMTR CALLBACK ****\n");
  }
  }
  fputc(terminals[dev].xmtrData & 0xFF, terminals[dev].out);
  fputc(serials[dev].xmtrData & 0xFF, serials[dev].out);
  terminals[dev].xmtrCtrl |= TERM_XMTR_RDY;
  serials[dev].xmtrCtrl |= SERIAL_XMTR_RDY;
  if (terminals[dev].xmtrCtrl & TERM_XMTR_IEN) {
  if (serials[dev].xmtrCtrl & SERIAL_XMTR_IEN) {
    /* raise terminal xmtr interrupt */
    /* raise serial line xmtr interrupt */
    cpuSetInterrupt(terminals[dev].xmtrIRQ);
    cpuSetInterrupt(serials[dev].xmtrIRQ);
  }
  }
}
}
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
Word termRead(Word addr) {
Word serialRead(Word addr) {
  int dev, reg;
  int dev, reg;
  Word data;
  Word data;
 
 
  if (debug) {
  if (debug) {
    cPrintf("\n**** TERM READ from 0x%08X", addr);
    cPrintf("\n**** SERIAL READ from 0x%08X", addr);
  }
  }
  dev = addr >> 12;
  dev = addr >> 12;
  if (dev >= numTerminals) {
  if (dev >= nSerials) {
    /* illegal device */
    /* illegal device */
    throwException(EXC_BUS_TIMEOUT);
    throwException(EXC_BUS_TIMEOUT);
  }
  }
  reg = addr & 0x0FFF;
  reg = addr & 0x0FFF;
  if (reg == TERM_RCVR_CTRL) {
  if (reg == SERIAL_RCVR_CTRL) {
    data = terminals[dev].rcvrCtrl;
    data = serials[dev].rcvrCtrl;
  } else
  } else
  if (reg == TERM_RCVR_DATA) {
  if (reg == SERIAL_RCVR_DATA) {
    terminals[dev].rcvrCtrl &= ~TERM_RCVR_RDY;
    serials[dev].rcvrCtrl &= ~SERIAL_RCVR_RDY;
    if (terminals[dev].rcvrCtrl & TERM_RCVR_IEN) {
    if (serials[dev].rcvrCtrl & SERIAL_RCVR_IEN) {
      /* lower terminal rcvr interrupt */
      /* lower serial line rcvr interrupt */
      cpuResetInterrupt(terminals[dev].rcvrIRQ);
      cpuResetInterrupt(serials[dev].rcvrIRQ);
    }
    }
    data = terminals[dev].rcvrData;
    data = serials[dev].rcvrData;
  } else
  } else
  if (reg == TERM_XMTR_CTRL) {
  if (reg == SERIAL_XMTR_CTRL) {
    data = terminals[dev].xmtrCtrl;
    data = serials[dev].xmtrCtrl;
  } else
  } else
  if (reg == TERM_XMTR_DATA) {
  if (reg == SERIAL_XMTR_DATA) {
    /* this register is write-only */
    /* this register is write-only */
    throwException(EXC_BUS_TIMEOUT);
    throwException(EXC_BUS_TIMEOUT);
  } else {
  } else {
    /* illegal register */
    /* illegal register */
    throwException(EXC_BUS_TIMEOUT);
    throwException(EXC_BUS_TIMEOUT);
Line 130... Line 130...
  }
  }
  return data;
  return data;
}
}
 
 
 
 
void termWrite(Word addr, Word data) {
void serialWrite(Word addr, Word data) {
  int dev, reg;
  int dev, reg;
 
 
  if (debug) {
  if (debug) {
    cPrintf("\n**** TERM WRITE to 0x%08X, data = 0x%08X ****\n",
    cPrintf("\n**** SERIAL WRITE to 0x%08X, data = 0x%08X ****\n",
            addr, data);
            addr, data);
  }
  }
  dev = addr >> 12;
  dev = addr >> 12;
  if (dev >= numTerminals) {
  if (dev >= nSerials) {
    /* illegal device */
    /* illegal device */
    throwException(EXC_BUS_TIMEOUT);
    throwException(EXC_BUS_TIMEOUT);
  }
  }
  reg = addr & 0x0FFF;
  reg = addr & 0x0FFF;
  if (reg == TERM_RCVR_CTRL) {
  if (reg == SERIAL_RCVR_CTRL) {
    if (data & TERM_RCVR_IEN) {
    if (data & SERIAL_RCVR_IEN) {
      terminals[dev].rcvrCtrl |= TERM_RCVR_IEN;
      serials[dev].rcvrCtrl |= SERIAL_RCVR_IEN;
    } else {
    } else {
      terminals[dev].rcvrCtrl &= ~TERM_RCVR_IEN;
      serials[dev].rcvrCtrl &= ~SERIAL_RCVR_IEN;
    }
    }
    if (data & TERM_RCVR_RDY) {
    if (data & SERIAL_RCVR_RDY) {
      terminals[dev].rcvrCtrl |= TERM_RCVR_RDY;
      serials[dev].rcvrCtrl |= SERIAL_RCVR_RDY;
    } else {
    } else {
      terminals[dev].rcvrCtrl &= ~TERM_RCVR_RDY;
      serials[dev].rcvrCtrl &= ~SERIAL_RCVR_RDY;
    }
    }
    if ((terminals[dev].rcvrCtrl & TERM_RCVR_IEN) != 0 &&
    if ((serials[dev].rcvrCtrl & SERIAL_RCVR_IEN) != 0 &&
        (terminals[dev].rcvrCtrl & TERM_RCVR_RDY) != 0) {
        (serials[dev].rcvrCtrl & SERIAL_RCVR_RDY) != 0) {
      /* raise terminal rcvr interrupt */
      /* raise serial line rcvr interrupt */
      cpuSetInterrupt(terminals[dev].rcvrIRQ);
      cpuSetInterrupt(serials[dev].rcvrIRQ);
    } else {
    } else {
      /* lower terminal rcvr interrupt */
      /* lower serial line rcvr interrupt */
      cpuResetInterrupt(terminals[dev].rcvrIRQ);
      cpuResetInterrupt(serials[dev].rcvrIRQ);
    }
    }
  } else
  } else
  if (reg == TERM_RCVR_DATA) {
  if (reg == SERIAL_RCVR_DATA) {
    /* this register is read-only */
    /* this register is read-only */
    throwException(EXC_BUS_TIMEOUT);
    throwException(EXC_BUS_TIMEOUT);
  } else
  } else
  if (reg == TERM_XMTR_CTRL) {
  if (reg == SERIAL_XMTR_CTRL) {
    if (data & TERM_XMTR_IEN) {
    if (data & SERIAL_XMTR_IEN) {
      terminals[dev].xmtrCtrl |= TERM_XMTR_IEN;
      serials[dev].xmtrCtrl |= SERIAL_XMTR_IEN;
    } else {
    } else {
      terminals[dev].xmtrCtrl &= ~TERM_XMTR_IEN;
      serials[dev].xmtrCtrl &= ~SERIAL_XMTR_IEN;
    }
    }
    if (data & TERM_XMTR_RDY) {
    if (data & SERIAL_XMTR_RDY) {
      terminals[dev].xmtrCtrl |= TERM_XMTR_RDY;
      serials[dev].xmtrCtrl |= SERIAL_XMTR_RDY;
    } else {
    } else {
      terminals[dev].xmtrCtrl &= ~TERM_XMTR_RDY;
      serials[dev].xmtrCtrl &= ~SERIAL_XMTR_RDY;
    }
    }
    if ((terminals[dev].xmtrCtrl & TERM_XMTR_IEN) != 0 &&
    if ((serials[dev].xmtrCtrl & SERIAL_XMTR_IEN) != 0 &&
        (terminals[dev].xmtrCtrl & TERM_XMTR_RDY) != 0) {
        (serials[dev].xmtrCtrl & SERIAL_XMTR_RDY) != 0) {
      /* raise terminal xmtr interrupt */
      /* raise serial line xmtr interrupt */
      cpuSetInterrupt(terminals[dev].xmtrIRQ);
      cpuSetInterrupt(serials[dev].xmtrIRQ);
    } else {
    } else {
      /* lower terminal xmtr interrupt */
      /* lower serial line xmtr interrupt */
      cpuResetInterrupt(terminals[dev].xmtrIRQ);
      cpuResetInterrupt(serials[dev].xmtrIRQ);
    }
    }
  } else
  } else
  if (reg == TERM_XMTR_DATA) {
  if (reg == SERIAL_XMTR_DATA) {
    terminals[dev].xmtrData = data & 0xFF;
    serials[dev].xmtrData = data & 0xFF;
    terminals[dev].xmtrCtrl &= ~TERM_XMTR_RDY;
    serials[dev].xmtrCtrl &= ~SERIAL_XMTR_RDY;
    if (terminals[dev].xmtrCtrl & TERM_XMTR_IEN) {
    if (serials[dev].xmtrCtrl & SERIAL_XMTR_IEN) {
      /* lower terminal xmtr interrupt */
      /* lower serial line xmtr interrupt */
      cpuResetInterrupt(terminals[dev].xmtrIRQ);
      cpuResetInterrupt(serials[dev].xmtrIRQ);
    }
    }
    timerStart(TERM_XMTR_USEC, xmtrCallback, dev);
    timerStart(SERIAL_XMTR_USEC, xmtrCallback, dev);
  } else {
  } else {
    /* illegal register */
    /* illegal register */
    throwException(EXC_BUS_TIMEOUT);
    throwException(EXC_BUS_TIMEOUT);
  }
  }
}
}
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
void termReset(void) {
void serialReset(void) {
  int i;
  int i;
 
 
  cPrintf("Resetting Terminals...\n");
  cPrintf("Resetting Serial Lines...\n");
  for (i = 0; i < numTerminals; i++) {
  for (i = 0; i < nSerials; i++) {
    terminals[i].rcvrCtrl = 0;
    serials[i].rcvrCtrl = 0;
    terminals[i].rcvrData = 0;
    serials[i].rcvrData = 0;
    terminals[i].rcvrIRQ = IRQ_TERM_0_RCVR + 2 * i;
    serials[i].rcvrIRQ = IRQ_SERIAL_0_RCVR + 2 * i;
    timerStart(TERM_RCVR_USEC, rcvrCallback, i);
    timerStart(SERIAL_RCVR_USEC, rcvrCallback, i);
    terminals[i].xmtrCtrl = TERM_XMTR_RDY;
    serials[i].xmtrCtrl = SERIAL_XMTR_RDY;
    terminals[i].xmtrData = 0;
    serials[i].xmtrData = 0;
    terminals[i].xmtrIRQ = IRQ_TERM_0_XMTR + 2 * i;
    serials[i].xmtrIRQ = IRQ_SERIAL_0_XMTR + 2 * i;
  }
  }
}
}
 
 
 
 
static void makeRaw(int fd) {
static void makeRaw(int fd) {
Line 234... Line 234...
  t.c_cflag |= CS8;
  t.c_cflag |= CS8;
  tcsetattr(fd, TCSANOW, &t);
  tcsetattr(fd, TCSANOW, &t);
}
}
 
 
 
 
void termInit(int numTerms, Bool hasTerm[]) {
void serialInit(int numSerials, Bool connectTerminals[]) {
  int i;
  int i;
  int master;
  int master;
  char slavePath[100];
  char slavePath[100];
  int slave;
  int slave;
  char termTitle[100];
  char termTitle[100];
  char termSlave[100];
  char termSlave[100];
 
 
  numTerminals = numTerms;
  nSerials = numSerials;
  for (i = 0; i < numTerminals; i++) {
  for (i = 0; i < nSerials; i++) {
    /* open pseudo terminal */
    /* open pseudo terminal */
    master = open("/dev/ptmx", O_RDWR | O_NONBLOCK);
    master = open("/dev/ptmx", O_RDWR | O_NONBLOCK);
    if (master < 0) {
    if (master < 0) {
      error("cannot open pseudo terminal master for serial line %d", i);
      error("cannot open pseudo terminal master for serial line %d", i);
    }
    }
Line 256... Line 256...
    strcpy(slavePath, ptsname(master));
    strcpy(slavePath, ptsname(master));
    if (debug) {
    if (debug) {
      cPrintf("pseudo terminal %d: master fd = %d, slave path = '%s'\n",
      cPrintf("pseudo terminal %d: master fd = %d, slave path = '%s'\n",
              i, master, slavePath);
              i, master, slavePath);
    }
    }
    if (hasTerm[i]) {
    if (connectTerminals[i]) {
      /* connect a terminal to the serial line */
      /* connect a terminal to the serial line */
      /* i.e., fork and exec a new xterm process */
      /* i.e., fork and exec a new xterm process */
      terminals[i].pid = fork();
      serials[i].pid = fork();
      if (terminals[i].pid < 0) {
      if (serials[i].pid < 0) {
        error("cannot fork xterm process for serial line %d", i);
        error("cannot fork xterm process for serial line %d", i);
      }
      }
      if (terminals[i].pid == 0) {
      if (serials[i].pid == 0) {
        /* terminal process */
        /* terminal process */
        setpgid(0, 0);
        setpgid(0, 0);
        close(master);
        close(master);
        /* open and configure pseudo terminal slave */
        /* open and configure pseudo terminal slave */
        slave = open(slavePath, O_RDWR | O_NONBLOCK);
        slave = open(slavePath, O_RDWR | O_NONBLOCK);
Line 281... Line 281...
        execlp("xterm", "xterm", "-title", termTitle, termSlave, NULL);
        execlp("xterm", "xterm", "-title", termTitle, termSlave, NULL);
        error("cannot exec xterm process for serial line %d", i);
        error("cannot exec xterm process for serial line %d", i);
      }
      }
    } else {
    } else {
      /* leave serial line unconnected */
      /* leave serial line unconnected */
      terminals[i].pid = 0;
      serials[i].pid = 0;
      cPrintf("Serial line %d can be accessed by opening device '%s'.\n",
      cPrintf("Serial line %d can be accessed by opening device '%s'.\n",
              i, slavePath);
              i, slavePath);
    }
    }
    fcntl(master, F_SETFL, O_NONBLOCK);
    fcntl(master, F_SETFL, O_NONBLOCK);
    terminals[i].in = fdopen(master, "r");
    serials[i].in = fdopen(master, "r");
    setvbuf(terminals[i].in, NULL, _IONBF, 0);
    setvbuf(serials[i].in, NULL, _IONBF, 0);
    terminals[i].out = fdopen(master, "w");
    serials[i].out = fdopen(master, "w");
    setvbuf(terminals[i].out, NULL, _IONBF, 0);
    setvbuf(serials[i].out, NULL, _IONBF, 0);
    if (hasTerm[i]) {
    if (connectTerminals[i]) {
      /* skip the window id written by xterm */
      /* skip the window id written by xterm */
      while (fgetc(terminals[i].in) != '\n') ;
      while (fgetc(serials[i].in) != '\n') ;
    }
    }
  }
  }
  termReset();
  serialReset();
}
}
 
 
 
 
void termExit(void) {
void serialExit(void) {
  int i;
  int i;
 
 
  /* kill and wait for all xterm processes */
  /* kill and wait for all xterm processes */
  for (i = 0; i < numTerminals; i++) {
  for (i = 0; i < nSerials; i++) {
    if (terminals[i].pid > 0) {
    if (serials[i].pid > 0) {
      kill(terminals[i].pid, SIGKILL);
      kill(serials[i].pid, SIGKILL);
      waitpid(terminals[i].pid, NULL, 0);
      waitpid(serials[i].pid, NULL, 0);
    }
    }
  }
  }
}
}
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.