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

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.24/] [sim/] [term.c] - Blame information for rev 211

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 8 hellwig
/*
2
 * term.c -- terminal simulation
3
 */
4
 
5
 
6
#ifdef __linux__
7
#define _XOPEN_SOURCE
8
#endif
9
 
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <string.h>
13
#include <setjmp.h>
14
#include <signal.h>
15
#include <sys/types.h>
16
#include <sys/wait.h>
17
#include <unistd.h>
18
#include <fcntl.h>
19
#include <termios.h>
20
 
21
#include "common.h"
22
#include "console.h"
23
#include "error.h"
24
#include "except.h"
25
#include "cpu.h"
26
#include "timer.h"
27
#include "term.h"
28
 
29
 
30
/**************************************************************/
31
 
32
 
33
static Bool debug = false;
34
 
35
 
36
typedef struct {
37
  pid_t pid;
38
  FILE *in;
39
  FILE *out;
40
  Word rcvrCtrl;
41
  Word rcvrData;
42
  int rcvrIRQ;
43
  Word xmtrCtrl;
44
  Word xmtrData;
45
  int xmtrIRQ;
46
} Terminal;
47
 
48
 
49
static Terminal terminals[MAX_NTERMS];
50
static int numTerminals;
51
 
52
 
53
/**************************************************************/
54
 
55
 
56
static void rcvrCallback(int dev) {
57
  int c;
58
 
59
  if (debug) {
60
    cPrintf("\n**** TERM RCVR CALLBACK ****\n");
61
  }
62 25 hellwig
  timerStart(TERM_RCVR_USEC, rcvrCallback, dev);
63 8 hellwig
  c = fgetc(terminals[dev].in);
64
  if (c == EOF) {
65
    /* no character typed */
66
    return;
67
  }
68
  /* any character typed */
69
  terminals[dev].rcvrData = c & 0xFF;
70
  terminals[dev].rcvrCtrl |= TERM_RCVR_RDY;
71
  if (terminals[dev].rcvrCtrl & TERM_RCVR_IEN) {
72
    /* raise terminal rcvr interrupt */
73
    cpuSetInterrupt(terminals[dev].rcvrIRQ);
74
  }
75
}
76
 
77
 
78
static void xmtrCallback(int dev) {
79
  if (debug) {
80
    cPrintf("\n**** TERM XMTR CALLBACK ****\n");
81
  }
82
  fputc(terminals[dev].xmtrData & 0xFF, terminals[dev].out);
83
  terminals[dev].xmtrCtrl |= TERM_XMTR_RDY;
84
  if (terminals[dev].xmtrCtrl & TERM_XMTR_IEN) {
85
    /* raise terminal xmtr interrupt */
86
    cpuSetInterrupt(terminals[dev].xmtrIRQ);
87
  }
88
}
89
 
90
 
91
/**************************************************************/
92
 
93
 
94
Word termRead(Word addr) {
95
  int dev, reg;
96
  Word data;
97
 
98
  if (debug) {
99
    cPrintf("\n**** TERM READ from 0x%08X", addr);
100
  }
101 25 hellwig
  dev = addr >> 12;
102 8 hellwig
  if (dev >= numTerminals) {
103
    /* illegal device */
104
    throwException(EXC_BUS_TIMEOUT);
105
  }
106 25 hellwig
  reg = addr & 0x0FFF;
107 8 hellwig
  if (reg == TERM_RCVR_CTRL) {
108
    data = terminals[dev].rcvrCtrl;
109
  } else
110
  if (reg == TERM_RCVR_DATA) {
111
    terminals[dev].rcvrCtrl &= ~TERM_RCVR_RDY;
112
    if (terminals[dev].rcvrCtrl & TERM_RCVR_IEN) {
113
      /* lower terminal rcvr interrupt */
114
      cpuResetInterrupt(terminals[dev].rcvrIRQ);
115
    }
116
    data = terminals[dev].rcvrData;
117
  } else
118
  if (reg == TERM_XMTR_CTRL) {
119
    data = terminals[dev].xmtrCtrl;
120
  } else
121
  if (reg == TERM_XMTR_DATA) {
122
    /* this register is write-only */
123
    throwException(EXC_BUS_TIMEOUT);
124
  } else {
125
    /* illegal register */
126
    throwException(EXC_BUS_TIMEOUT);
127
  }
128
  if (debug) {
129
    cPrintf(", data = 0x%08X ****\n", data);
130
  }
131
  return data;
132
}
133
 
134
 
135
void termWrite(Word addr, Word data) {
136
  int dev, reg;
137
 
138
  if (debug) {
139
    cPrintf("\n**** TERM WRITE to 0x%08X, data = 0x%08X ****\n",
140
            addr, data);
141
  }
142 25 hellwig
  dev = addr >> 12;
143 8 hellwig
  if (dev >= numTerminals) {
144
    /* illegal device */
145
    throwException(EXC_BUS_TIMEOUT);
146
  }
147 25 hellwig
  reg = addr & 0x0FFF;
148 8 hellwig
  if (reg == TERM_RCVR_CTRL) {
149
    if (data & TERM_RCVR_IEN) {
150
      terminals[dev].rcvrCtrl |= TERM_RCVR_IEN;
151
    } else {
152
      terminals[dev].rcvrCtrl &= ~TERM_RCVR_IEN;
153
    }
154
    if (data & TERM_RCVR_RDY) {
155
      terminals[dev].rcvrCtrl |= TERM_RCVR_RDY;
156
    } else {
157
      terminals[dev].rcvrCtrl &= ~TERM_RCVR_RDY;
158
    }
159
    if ((terminals[dev].rcvrCtrl & TERM_RCVR_IEN) != 0 &&
160
        (terminals[dev].rcvrCtrl & TERM_RCVR_RDY) != 0) {
161
      /* raise terminal rcvr interrupt */
162
      cpuSetInterrupt(terminals[dev].rcvrIRQ);
163
    } else {
164
      /* lower terminal rcvr interrupt */
165
      cpuResetInterrupt(terminals[dev].rcvrIRQ);
166
    }
167
  } else
168
  if (reg == TERM_RCVR_DATA) {
169
    /* this register is read-only */
170
    throwException(EXC_BUS_TIMEOUT);
171
  } else
172
  if (reg == TERM_XMTR_CTRL) {
173
    if (data & TERM_XMTR_IEN) {
174
      terminals[dev].xmtrCtrl |= TERM_XMTR_IEN;
175
    } else {
176
      terminals[dev].xmtrCtrl &= ~TERM_XMTR_IEN;
177
    }
178
    if (data & TERM_XMTR_RDY) {
179
      terminals[dev].xmtrCtrl |= TERM_XMTR_RDY;
180
    } else {
181
      terminals[dev].xmtrCtrl &= ~TERM_XMTR_RDY;
182
    }
183
    if ((terminals[dev].xmtrCtrl & TERM_XMTR_IEN) != 0 &&
184
        (terminals[dev].xmtrCtrl & TERM_XMTR_RDY) != 0) {
185
      /* raise terminal xmtr interrupt */
186
      cpuSetInterrupt(terminals[dev].xmtrIRQ);
187
    } else {
188
      /* lower terminal xmtr interrupt */
189
      cpuResetInterrupt(terminals[dev].xmtrIRQ);
190
    }
191
  } else
192
  if (reg == TERM_XMTR_DATA) {
193
    terminals[dev].xmtrData = data & 0xFF;
194
    terminals[dev].xmtrCtrl &= ~TERM_XMTR_RDY;
195
    if (terminals[dev].xmtrCtrl & TERM_XMTR_IEN) {
196
      /* lower terminal xmtr interrupt */
197
      cpuResetInterrupt(terminals[dev].xmtrIRQ);
198
    }
199 25 hellwig
    timerStart(TERM_XMTR_USEC, xmtrCallback, dev);
200 8 hellwig
  } else {
201
    /* illegal register */
202
    throwException(EXC_BUS_TIMEOUT);
203
  }
204
}
205
 
206
 
207
/**************************************************************/
208
 
209
 
210
void termReset(void) {
211
  int i;
212
 
213
  cPrintf("Resetting Terminals...\n");
214
  for (i = 0; i < numTerminals; i++) {
215
    terminals[i].rcvrCtrl = 0;
216
    terminals[i].rcvrData = 0;
217
    terminals[i].rcvrIRQ = IRQ_TERM_0_RCVR + 2 * i;
218 25 hellwig
    timerStart(TERM_RCVR_USEC, rcvrCallback, i);
219 8 hellwig
    terminals[i].xmtrCtrl = TERM_XMTR_RDY;
220
    terminals[i].xmtrData = 0;
221
    terminals[i].xmtrIRQ = IRQ_TERM_0_XMTR + 2 * i;
222
  }
223
}
224
 
225
 
226
static int openPty(int *master, int *slave, char *name) {
227
  /* try to open master */
228
  strcpy(name, "/dev/ptmx");
229
  *master = open(name, O_RDWR | O_NONBLOCK);
230
  if (*master < 0) {
231
    /* open failed */
232
    return -1;
233
  }
234
  grantpt(*master);
235
  unlockpt(*master);
236
  /* master opened, try to open slave */
237
  strcpy(name, ptsname(*master));
238
  *slave = open(name, O_RDWR | O_NONBLOCK);
239
  if (*slave < 0) {
240
    /* open failed, close master */
241
    close(*master);
242
    return -1;
243
  }
244
  /* all is well */
245
  return 0;
246
}
247
 
248
 
249
static void makeRaw(struct termios *tp) {
250
  tp->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
251
  tp->c_oflag &= ~OPOST;
252
  tp->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
253
  tp->c_cflag &= ~(CSIZE|PARENB);
254
  tp->c_cflag |= CS8;
255
}
256
 
257
 
258
void termInit(int numTerms) {
259
  int master, slave;
260
  char ptyName[100];
261
  char ptyTitle[100];
262
  struct termios termios;
263
  int i;
264
 
265
  numTerminals = numTerms;
266
  for (i = 0; i < numTerminals; i++) {
267
    /* open pseudo terminal */
268
    if (openPty(&master, &slave, ptyName) < 0) {
269
      error("cannot open pseudo terminal %d", i);
270
    }
271
    if (debug) {
272
      cPrintf("pseudo terminal '%s': master fd = %d, slave fd = %d\n",
273
              ptyName, master, slave);
274
    }
275
    /* set mode to raw */
276
    tcgetattr(slave, &termios);
277
    makeRaw(&termios);
278
    tcsetattr(slave, TCSANOW, &termios);
279
    /* fork and exec a new xterm */
280
    terminals[i].pid = fork();
281
    if (terminals[i].pid < 0) {
282
      error("cannot fork xterm process %d", i);
283
    }
284
    if (terminals[i].pid == 0) {
285
      /* terminal process */
286
      setpgid(0, 0);
287
      close(2);
288
      close(master);
289
      sprintf(ptyName, "-Sab%d", slave);
290
      sprintf(ptyTitle, "ECO32 Terminal %d", i);
291
      execlp("xterm", "xterm", "-title", ptyTitle, ptyName, NULL);
292
      error("cannot exec xterm process %d", i);
293
    }
294
    fcntl(master, F_SETFL, O_NONBLOCK);
295
    terminals[i].in = fdopen(master, "r");
296
    setvbuf(terminals[i].in, NULL, _IONBF, 0);
297
    terminals[i].out = fdopen(master, "w");
298
    setvbuf(terminals[i].out, NULL, _IONBF, 0);
299
    /* skip the window id written by xterm */
300
    while (fgetc(terminals[i].in) != '\n') ;
301
  }
302
  termReset();
303
}
304
 
305
 
306
void termExit(void) {
307
  int i;
308
 
309
  /* kill and wait for all xterm processes */
310
  for (i = 0; i < numTerminals; i++) {
311
    if (terminals[i].pid > 0) {
312
      kill(terminals[i].pid, SIGKILL);
313
      waitpid(terminals[i].pid, NULL, 0);
314
    }
315
  }
316
}

powered by: WebSVN 2.1.0

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