Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / serial_4v / serial.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: serial.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#include "serial_4v.h"
22
23
24static const char *serial_4v_help = "\
25tip based SAM N2 console module (for Legion's virtual console device)\n\
26Sysconf format is :\n\
27sysconf serial_4v <instance_name> base=<start_addr> size=<map size> [log[=<filename>]] [pop] [fg=<color>] [bg=<color>] [font=<font>] [dnkxoe] [raw] [-a] [T=<title>] [e=<command>]\n\
28'base' is the start address of memory mapped address, of the device CSRs\n\
29'size' is the size of the CSR space\n\
30'log' enables logging of console o/p to a file. The default log file is <instance_name>.log\n\
31 'raw' - optional boolean parameter, if specified enables unbuffered logging of console o/p, if logging is enabled\n\
32 The log file is opened in append mode if -a is not specified\n\
33'pop' is boolean arg which if present will open an xterm window for console o/p\n\
34'e, e, command\' is optional argument to set command instead of /bin/tip\n\
35'T, T, title\' is optional argument to set xterm title instead of instance name\n\
36'fg, bg, font, T' are optional arguments to set foreground, background and font of the xterm window\n\
37'dnkxoe' - do not kill xterm on exit, default - window killed\n\
38For UI help type <instance name>\n\
39For module specific info type \"modinfo <instance name>\"";
40
41Module *Module::create(const char *_modname, const char *_instance_name){
42 return new serial4v(_modname, _instance_name);
43}
44const char * serial4v::get_help(){
45 return Module::get_help_string();
46}
47
48const char *
49Module::get_help_string(){
50 return serial_4v_help;
51}
52
53serial4v::serial4v(const char * modname,const char * instance_name)
54 :
55 Module(modname,instance_name),
56 title(0)
57{
58 log = false;
59 start_pa = -1;
60 end_pa = 0;
61 size = 0;
62 logfile = 0;
63 pop = false;
64 portConName = 0;
65 portCon = -1;
66 pthread_mutex_init(&mutty,0);
67 scratch = 0;
68 line_status = DS_LSTAT_TX_EMPTY | DS_LSTAT_TX_HOLD;
69 in.count = in.head = in.tail = 0;
70 in.size = MaxBuf;
71
72 font = strdup("-dec-terminal-medium-r-normal-*-14-140-*-75-c-80-iso8859-1");
73 bg = strdup("grey90");
74 fg = strdup("black");
75 exec = strdup("/bin/tip");
76 kill_xterm_on_exit = true;
77 raw =false;
78 append = true;
79
80 mmi_register_instance_cmd(getInstance(),serial_4v_help,serial_4v_ui_cmd);
81}
82
83bool serial4v::parse_arg(const char * arg){
84 if(!strcmp("pop",arg)){
85 pop = true;
86 return true;
87 }else if(!strcmp("dnkxoe",arg)){
88 kill_xterm_on_exit = false;
89 return true;
90 }else if(!strcmp("raw",arg)){
91 raw = true;
92 return true;
93 }else if(!strcmp("-a",arg)){
94 append = false;
95 return true;
96 }else if(!strncmp("log",arg,3)){
97 log = true;
98 if(arg[3] == '='){
99 logfile = strdup(arg+4);
100 debug_more("%s: console log enabled. Log file %s",getName(),logfile);
101 }else
102 debug_more("%s: console log enabled. Log file %s.log",getName(),getName());
103 return true;
104 }else if(argval("base",arg,&start_pa)){
105 debug_more("%s: base_pa %llx\n",getName(), start_pa);
106 return true;
107 }else if(argval("size",arg,&size)){
108 debug_more("%s: size %llx, end_pa %llx\n",getName(), size, start_pa + size - 1);
109 return true;
110 }else if(argval("bg",arg,&bg)){
111 debug_more("%s: bg - %s\n",getName(), bg);
112 return true;
113 }else if(argval("fg",arg,&fg)){
114 debug_more("%s: fg - %s\n",getName(), fg);
115 return true;
116 }else if(argval("font",arg,&font)){
117 debug_more("%s: font - %s\n",getName(), font);
118 return true;
119 }else if(argval("T",arg,&title)){
120 debug_more("%s: T - %s\n",getName(), title);
121 return true;
122 }else if(argval("e",arg,&exec)){
123 debug_more("%s: e - %s\n",getName(), exec);
124 return true;
125 }else
126 return false;
127}
128
129
130bool serial4v::check_args(){
131
132 if(start_pa == -1){
133 debug_err("%s:must specify start address\n",getName());
134 return false;
135 }else if(size == 0){
136 debug_err("%s:must specify size of address mapping\n",getName());
137 return false;
138 }else
139 return true;
140}
141
142void serial4v::init_done(){
143
144 if (!title)
145 {
146 title = (const char*)malloc(strlen(getName() + 1));
147 strcpy((char*)title,getName());
148 }
149 Console = new console();
150
151 if(fg) Console->setFg(fg);
152 if(bg) Console->setBg(bg);
153 if(font) Console->setFont(font);
154 if(exec) Console->setExec(exec);
155 if(title) Console->setTitle(title);
156
157 portCon = Console->getTerminal((char*)title,10000,getConsoleIp, this, &portConName, pop);
158 fprintf(stderr,"%s : to connect to console: tip %s\n",getName(),portConName);
159 Console->setId(getName());
160
161
162
163 if(log){
164 if(!logfile){
165 char * logname = (char*)malloc( strlen( getName() ) + strlen(".log") + 1 );
166 strcpy(logname,getName());
167 strcat(logname,".log");
168 logfile = strdup(logname);
169 free(logname);
170 }
171 Console->log(portCon,true,logfile,raw,append);
172 }
173 if(mmi_map_physio(start_pa, size, (void *) this, serial4v_physio_access) != 0) {
174 debug_err("%s fatal error: unaable to map IO space\n");
175 exit(1);
176 }
177}
178
179
180void serial4v::getConsoleIp(void *data,unsigned char *ip, int port){
181 serial4v * self = (serial4v *)data;
182
183 pthread_mutex_lock(&self->mutty);
184
185 if(self->in.count < self->in.size){
186 self->in.bufp[self->in.tail] = *ip;
187 self->in.tail++;
188 if(self->in.tail >= self->in.size)
189 self->in.tail = 0;
190 self->in.count++;
191 self->line_status |= DS_LSTAT_DATA_READY;
192 }else{
193 if(!(self->line_status & DS_LSTAT_OVERRUN))
194 self->debug_err("%s: buffer overrun",self->getName());
195 self->line_status |= DS_LSTAT_OVERRUN;
196 }
197 pthread_mutex_unlock(&self->mutty);
198}
199
200
201
202void serial4v::serial4v_ld (uint64_t paddr, uint64_t *buf, int size){
203 ds_reg_t reg;
204 uint64_t val;
205
206 reg = (ds_reg_t) (paddr & 0xfff) ;
207 val = 0;
208 switch (reg) {
209 case DS_Input:
210 pthread_mutex_lock(&mutty);
211 if (in.count == 0) {
212 val = 0;
213 line_status &= ~DS_LSTAT_DATA_READY;
214 }else{
215 val = in.bufp[in.head];
216 in.head ++;
217 if (in.head >= in.size)
218 in.head = 0;
219 in.count --;
220 if (in.count == 0)
221 line_status &= ~DS_LSTAT_DATA_READY;
222 }
223 pthread_mutex_unlock(&mutty);
224 break;
225 case DS_IntEnable:
226 break;
227 case DS_IntIdent:
228 break;
229 case DS_LineCtrl:
230 break;
231 case DS_ModemCtrl:
232 break;
233 case DS_LineStatus:
234 pthread_mutex_lock(&mutty);
235 val = line_status;
236 pthread_mutex_unlock(&mutty);
237 break;
238 case DS_ModemStatus:
239 break;
240 case DS_Scratch:
241 scratch = val & 0xff;
242 break;
243 case DS_DivLo:
244 break;
245 case DS_DivHi:
246 break;
247 default:
248 debug_err("%s: rd access to unimplemented register 0x%x\n",getName());
249 val = 0;
250 break;
251 }
252 *buf = val;
253 return;
254}
255
256
257void serial4v::serial4v_st(uint64_t pa, uint64_t *buf, int sz){
258 ds_reg_t reg;
259 uint64_t val;
260 reg = (ds_reg_t) (pa & 0xfff);
261 val = *buf;
262
263 assert(sz == 1);
264
265 if (val > 0xff)
266 debug_err("%s:writing 0x%llx to console. Truncate to 8 bits\n",getName());
267
268 val &= 0xff;
269
270 switch (reg) {
271 case DS_Output:
272 {
273 uint8_t chr = *buf;
274 Console->writeTerminal(portCon, &chr, 1);
275 break;
276 }
277 case DS_IntEnable:
278 break;
279 case DS_FIFOCtrl:
280 break;
281 case DS_LineCtrl:
282 break;
283 case DS_ModemCtrl:
284 break;
285 case DS_LineStatus:
286 pthread_mutex_lock(&mutty);
287 line_status = (val & 0xff) | DS_LSTAT_TX_EMPTY | DS_LSTAT_TX_HOLD;
288 pthread_mutex_unlock(&mutty);
289 break;
290 case DS_ModemStatus:
291 break;
292 case DS_Scratch:
293 scratch = val & 0xff;
294 break;
295 case DS_DivLo:
296 break;
297 case DS_DivHi:
298 break;
299 default:
300 debug_err("%s: wr access to unimplemented register 0x%x\n",getName());
301 break;
302 }
303 return;
304}
305
306
307int serial4v::serial4v_physio_access(uint32_t cpuid, void* obj, uint64_t paddr,
308 mmi_bool_t wr, uint32_t size, uint64_t* buf, uint8_t bytemask){
309 serial4v* s = (serial4v*) obj;
310
311 if(wr)
312 s->serial4v_st(paddr,buf,size);
313 else
314 s->serial4v_ld(paddr,buf,size);
315 return 0;
316}
317
318int serial_4v_ui_cmd(void * obj, int argc, char * argv[]){
319 serial4v * i = (serial4v *)obj;
320 i->handle_ui(argc, argv);
321 return 0;
322}
323
324void serial4v::handle_ui(int argc, char * argv[]){
325 if(argc == 1){
326 ui_cmd_usage();
327 return;
328 }else if(!strcmp(argv[1],"send")){
329 if(argv[2]){
330 const int bufSize = 1024 * 10;
331 char buf[bufSize];
332 buf[0] = '\0';
333 // no error checking for command string to be longer than 10KB
334 for(int i = 2; i < argc; i++){
335 strcat(buf,argv[i]);
336 strcat(buf," ");
337 }
338 buf[strlen(buf) - 1] = '\n';
339
340 for(int i = 0; i < strlen(buf); i++)
341 getConsoleIp((void*)this,(uint8_t *)(buf + i),-1);
342 }else{
343 char buf[2];
344 buf[0] = '\n';
345 buf[1] = '\0';
346 for(int i = 0; i < strlen(buf); i++)
347 getConsoleIp((void*)this,(uint8_t *)(buf + i),-1);
348 }
349 }else if(!strcmp(argv[1],"sendfile")){
350 FILE * fp;
351 if(argv[2]){
352 fp = fopen(argv[2],"r");
353 if(fp){
354 uint8_t chr;
355 while(fread(&chr,1,1,fp))
356 getConsoleIp((void*)this,&chr,-1);
357 }
358 else
359 fprintf(stderr,"%s restore: error opening file <%s>\n",getName(),argv[2]);
360 }else
361 fprintf(stderr,"%s sendfile: no filename specified\n",getName());
362 }else if(!strcmp(argv[1],"dump")){
363 FILE * fp = stderr;
364 if(argv[2]){
365 fp = fopen(argv[2],"w");
366 if(!fp){
367 fprintf(stderr,"%s dump: error opening file <%s>\n",getName(),argv[2]);
368 fp = stderr;
369 }
370 }
371 dump(fp);
372 if(fp != stderr)
373 fclose(fp);
374 }else if(!strcmp(argv[1],"restore")){
375 FILE * fp;
376 if(argv[2]){
377 fp = fopen(argv[2],"r");
378 if(fp){
379 restore(fp);
380 fclose(fp);
381 }else
382 fprintf(stderr,"%s restore: error opening file <%s>\n",getName(),argv[2]);
383 }else
384 fprintf(stderr,"%s restore: no restore filename specified\n",getName());
385 }else if(!strcmp(argv[1],"debug")){
386 if(argv[2]){
387 debug_level = atoi(argv[2]);
388 fprintf(stderr,"%s: set debug level to %d\n",getName(),debug_level);
389 }else
390 fprintf(stderr,"%s: current debug level %d\n",getName(),debug_level);
391 }else if(!strcmp(argv[1],"pop")){
392 Console->pop_term(portCon);
393 }else if(!strcmp(argv[1],"kill")){
394 Console->kill_term(portCon);
395 }else if(!strcmp(argv[1],"fg")){
396 if(fg) free((void*)fg);
397 if(argv[2]){
398 fg = strdup(argv[2]);
399 Console->setFg(fg);
400 }else
401 fprintf(stderr," fg : %s\n", fg);
402 }else if(!strcmp(argv[1],"bg")){
403 if(bg) free((void*)bg);
404 if(argv[2]){
405 bg = strdup(argv[2]);
406 Console->setBg(bg);
407 }else
408 fprintf(stderr," bg : %s\n", bg);
409 }else if(!strcmp(argv[1],"font")){
410 if(font) free((void*)font);
411 if(argv[2]){
412 font = strdup(argv[2]);
413 Console->setFont(font);
414 }else
415 fprintf(stderr," font : %s\n", font);
416 }else if(!strcmp(argv[1],"T")){
417 if(title) free((void*)title);
418 if(argv[2]){
419 title = strdup(argv[2]);
420 Console->setTitle(title);
421 }else
422 fprintf(stderr," title : %s\n", title);
423 }else if(!strcmp(argv[1],"e")){
424 if(exec) free((void*)exec);
425 if(argv[2]){
426 exec = strdup(argv[2]);
427 Console->setExec(exec);
428 }else
429 fprintf(stderr," exec : %s\n", exec);
430 }else
431 debug_err("%s: unsupported UI command <%s>\n",getName(),argv[1]);
432 return;
433}