Commit | Line | Data |
---|---|---|
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 | ||
50 | extern serialInterface * systemConsole; | |
51 | typedef void (*serial_send)(void *, char *, int ); | |
52 | static int portnum = -1; | |
53 | ||
54 | ||
55 | struct 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 | ||
65 | static struct term terms[NUM_PORTS]; | |
66 | ||
67 | ///////////////////////////////////////////////// | |
68 | ||
69 | static 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 | ||
116 | static int xterm_pid = -1; | |
117 | int 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 | ||
134 | void 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 | ||
145 | int 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 | ||
182 | void 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 | ||
198 | static 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 | ||
216 | void term_fake_input (uint8_t *cmd, int l, int port) | |
217 | { | |
218 | systemConsole->chars_send((char *)cmd, systemConsole->portH); | |
219 | } | |
220 | ||
221 | ||
222 | extern volatile bool config_is_done; | |
223 | // volatile is needed, otherwise the compiler eliminates the | |
224 | // while loop as dead-code for opt version | |
225 | ||
226 | void 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 | } |