Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / blaze / term.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: term.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21/*
22 * Copyright (C) 2001 Sun Microsystems, Inc.
23 * All rights reserved.
24 */
25#pragma ident "@(#)1.16 07/11/19 term.cc"
26
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <sys/time.h>
30#include <assert.h>
31#include <fcntl.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <strings.h>
35#include <stropts.h>
36#include <unistd.h>
37#include <sys/wait.h>
38#include <signal.h>
39
40#include "types.h"
41#include "blaze_globals.h"
42#include "term.h"
43// Needed for FlexConfig
44#include "mmi.h"
45#include "ui.h"
46#include "serial_mod.h"
47
48//extern FILE *serial_file;
49
50extern serialInterface * systemConsole;
51typedef void (*serial_send)(void *, char *, int );
52static int portnum = -1;
53
54
55struct term {
56 bool_t initialized;
57 int port_fd;
58 int mport_fd;
59 char *port_name;
60 serial_send input;
61 void * cbData;
62 FILE *serial_output_file;
63};
64
65static struct term terms[NUM_PORTS];
66
67/////////////////////////////////////////////////
68
69static bool_t get_pty(char *name, int *sfd, int *mfd)
70{
71 if ((*mfd = open("/dev/ptmx", O_RDWR|O_NDELAY)) == -1) {
72 ui->error("serial: Cannot find a pseudo tty.\n");
73 return FALSE;
74 }
75
76 if (grantpt(*mfd) < 0) {
77 ui->error("serial: Could not grant access to slave pseudo tty\n");
78 ui->perror("grantpt");
79 close(*mfd);
80 return FALSE;
81 }
82
83 if (unlockpt(*mfd) < 0) {
84 ui->error("serial: Unable to unlock pseudo tty.\n");
85 ui->perror("unlockpt");
86 close(*mfd);
87 return FALSE;
88 }
89
90 strcpy(name, ptsname(*mfd));
91 *sfd = open(name, O_RDWR);
92
93 if (*sfd < 0) {
94 ui->error("serial: Unable to open slave side for %d\n", *mfd);
95 close(*mfd);
96 return FALSE;
97 }
98
99 if (ioctl(*sfd, I_PUSH, "ptem") < 0) {
100 ui->error("serial: Ioctl I_PUSH ptem failed\n");
101 ui->perror("ioctl i_push ptem");
102 close(*mfd);
103 return FALSE;
104 }
105
106 if (ioctl(*sfd, I_PUSH, "ldterm") < 0) {
107 ui->error("serial: Ioctl I_PUSH ldterm failed\n");
108 ui->perror("ioctl i_push ldterm");
109 close(*mfd);
110 return FALSE;
111 }
112
113 return TRUE;
114}
115
116static int xterm_pid = -1;
117int term_console (char *pty_dev, char *display)
118{
119 int pid = 0;
120
121 if ((pid = vfork()) == 0) {
122 execl("/usr/openwin/bin/xterm", "/usr/openwin/bin/xterm", "-display", display,
123 "-T", "blaze-sim-console", "-n", "blz-sim-con", "-sb", "-sl", "10000",
124 "-e", "/bin/tip", pty_dev, NULL);
125
126 // shouldn't get here
127 ui->perror("/usr/openwin/bin/xterm for blaze console");
128 exit(1);
129 }
130
131 return xterm_pid = pid;
132}
133
134void term_console_destroy ()
135{
136 if (xterm_pid != -1) {
137 ui->verbose("\nkilling console window (pid %d)\n", xterm_pid);
138 kill(xterm_pid, 9);
139 int deadpid = wait(NULL);
140 ui->verbose(" done\n");
141 }
142}
143
144
145int term_init(FILE *fp, serial_send fn, void *cbData,char **tty_name)
146{
147 char pty_name[20];
148
149 portnum++;
150 terms[portnum].initialized = FALSE;
151
152 if (fp == NULL) {
153 if (!get_pty(pty_name, &terms[portnum].port_fd,
154 &terms[portnum].mport_fd)) {
155 ui->error("TERM : get_pty failed\n");
156 return NULL;
157 }
158
159 chmod(pty_name,
160 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH |
161 S_IWOTH);
162 terms[portnum].port_name = strdup(pty_name);
163 terms[portnum].input = fn;
164 terms[portnum].cbData = cbData;
165 terms[portnum].initialized = TRUE;
166 terms[portnum].serial_output_file = fp;
167 *tty_name = strdup(pty_name);
168 }
169 else {
170 terms[portnum].serial_output_file = fp;
171 terms[portnum].port_name = NULL;
172 terms[portnum].input = fn;
173 terms[portnum].cbData = cbData;
174 terms[portnum].initialized = TRUE;
175 terms[portnum].mport_fd = -1;
176 terms[portnum].port_fd = -1;
177 *tty_name = strdup("Op redirected !!");
178 }
179 return portnum;
180}
181
182void term_write(unsigned char *c, int port)
183{
184 FILE *fp = terms[port].serial_output_file;
185
186 if (fp) {
187 if(*c == 0xd || *c == '\0')
188 return;
189 putc(*c, fp);
190 term_redirect_add (c[0]);
191 fflush(fp);
192 } else {
193 write(terms[port].mport_fd, c, 1);
194 term_redirect_add (c[0]) ;
195 }
196}
197
198static void term_read_ports(fd_set readfds)
199{
200 int i;
201 char chstr[2];
202
203 for (i = 0; i < NUM_PORTS; i++) {
204 if (FD_ISSET(terms[i].mport_fd, &readfds)) {
205 int nbytes;
206 uint8_t ch;
207
208 while ((nbytes = read(terms[i].mport_fd, &ch, 1)) == 1) {
209 sprintf(chstr,"%c", ch);
210 terms[i].input(terms[i].cbData,chstr,i);
211 }
212 }
213 }
214}
215
216void term_fake_input (uint8_t *cmd, int l, int port)
217{
218 systemConsole->chars_send((char *)cmd, systemConsole->portH);
219}
220
221
222extern volatile bool config_is_done;
223// volatile is needed, otherwise the compiler eliminates the
224// while loop as dead-code for opt version
225
226void term_thread(void *)
227{
228 int i, n;
229 fd_set readfds;
230
231 // spin loop until the sysconf modules are loaded and initialized
232 // not doing this results in a race condition where the select call is
233 // made before the terms[i] struct is initialzed. The effect is, no
234 // console input possible.
235 // the variable config_is_done is set to true after the init_done() has
236 // been called for all the sysconf modules.
237 // better approaches are possible but would need to much work and cleanup.
238 // untill later....
239 while(!config_is_done);
240
241 for (;;) {
242 FD_ZERO(&readfds);
243
244 for (i = 0; i <= portnum; i++) {
245 if (terms[i].initialized && terms[i].mport_fd != -1) {
246 FD_SET(terms[i].mport_fd, &readfds);
247 }
248 }
249
250 n = select(FD_SETSIZE, &readfds, (fd_set *)NULL,
251 (fd_set *)NULL, NULL);
252
253 switch (n) {
254 case -1: /* error */
255 break;
256 case 0: /* timeout */
257 break;
258 default: /* input available */
259 term_read_ports(readfds);
260 break;
261 }
262 }
263}