2003-04-13 Michael Snyder <msnyder@redhat.com>
[binutils-gdb.git] / gdb / rdi-share / unixcomm.c
1 /*
2 * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
3 *
4 * This software may be freely used, copied, modified, and distributed
5 * provided that the above copyright notice is preserved in all copies of the
6 * software.
7 */
8
9 /* -*-C-*-
10 *
11 * $Revision$
12 * $Date$
13 *
14 */
15
16 #ifdef __hpux
17 # define _POSIX_SOURCE 1
18 #endif
19
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <ctype.h>
23
24 #ifdef __hpux
25 # define _TERMIOS_INCLUDED
26 # include <sys/termio.h>
27 # undef _TERMIOS_INCLUDED
28 #else
29 # include <termios.h>
30 #endif
31
32 #include <string.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <stdarg.h>
36 #include <sys/types.h>
37 #include <sys/time.h>
38
39 #if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (bsdi)
40 #undef BSD
41 #include <sys/ioctl.h>
42 #endif
43
44 #ifdef sun
45 # include <sys/ioccom.h>
46 # ifdef __svr4__
47 # include <sys/bpp_io.h>
48 # else
49 # include <sbusdev/bpp_io.h>
50 # endif
51 #endif
52
53 #ifdef BSD
54 # ifdef sun
55 # include <sys/ttydev.h>
56 # endif
57 # ifdef __alpha
58 # include <sys/ioctl.h>
59 # else
60 # include <sys/filio.h>
61 # endif
62 #endif
63
64 #ifdef __hpux
65 # define _INCLUDE_HPUX_SOURCE
66 # include <sys/ioctl.h>
67 # undef _INCLUDE_HPUX_SOURCE
68 #endif
69
70 #include "host.h"
71 #include "unixcomm.h"
72
73 #define PP_TIMEOUT 1 /* seconds */
74
75 #ifdef sun
76 #define SERIAL_PREFIX "/dev/tty"
77 #define SERPORT1 "/dev/ttya"
78 #define SERPORT2 "/dev/ttyb"
79 #define PARPORT1 "/dev/bpp0"
80 #define PARPORT2 "/dev/bpp1"
81 #endif
82
83 #ifdef __hpux
84 #define SERIAL_PREFIX "/dev/tty"
85 #define SERPORT1 "/dev/tty00"
86 #define SERPORT2 "/dev/tty01"
87 #define PARPORT1 "/dev/ptr_parallel"
88 #define PARPORT2 "/dev/ptr_parallel"
89 #endif
90
91 #ifdef __linux__
92 #define SERIAL_PREFIX "/dev/ttyS"
93 #define SERPORT1 "/dev/ttyS0"
94 #define SERPORT2 "/dev/ttyS1"
95 #define PARPORT1 "/dev/par0"
96 #define PARPORT2 "/dev/par1"
97 #endif
98
99 #if defined(_WIN32) || defined (__CYGWIN__)
100 #define SERIAL_PREFIX "com"
101 #define SERPORT1 "com1"
102 #define SERPORT2 "com2"
103 #define PARPORT1 "lpt1"
104 #define PARPORT2 "lpt2"
105 #endif
106
107 #if !defined (SERIAL_PREFIX)
108 #define SERIAL_PREFIX "/dev/cuaa"
109 #define SERPORT1 "/dev/cuaa0"
110 #define SERPORT2 "/dev/cuaa1"
111 #define PARPORT1 "/dev/lpt0"
112 #define PARPORT2 "/dev/lpt1"
113 #endif
114
115
116
117
118 /*
119 * Parallel port output pins, used for signalling to target
120 */
121
122 #ifdef sun
123 struct bpp_pins bp;
124 #endif
125
126 static int serpfd = -1;
127 static int parpfd = -1;
128
129 extern const char *Unix_MatchValidSerialDevice(const char *name)
130 {
131 int i=0;
132 char *sername=NULL;
133
134 /* Accept no name as the default serial port */
135 if (name == NULL) {
136 return SERPORT1;
137 }
138
139 /* Look for the simple cases - 1,2,s,S,/dev/... first, and
140 * afterwards look for S=... clauses, which need parsing properly.
141 */
142
143 /* Accept /dev/tty* where * is limited */
144 if (strlen(name) == strlen(SERPORT1)
145 && strncmp(name, SERIAL_PREFIX, strlen (SERIAL_PREFIX)) == 0)
146 {
147 return name;
148 }
149
150 /* Accept "1" or "2" or "S" - S is equivalent to "1" */
151 if (strcmp(name, "1") == 0 ||
152 strcmp(name, "S") == 0 || strcmp(name, "s") == 0) {
153 return SERPORT1;
154 }
155 if (strcmp(name, "2") == 0) return SERPORT2;
156
157 /* It wasn't one of the simple cases, so now we have to parse it
158 * properly
159 */
160
161 do {
162 switch (name[i]) {
163 case ',':
164 /* Skip over commas */
165 i++;
166 break;
167
168 default:
169 return 0;
170 /* Unexpected character => error - not matched */
171
172 case 0:
173 /* End of string means return whatever we have matched */
174 return sername;
175
176 case 's':
177 case 'S':
178 case 'h':
179 case 'H': {
180 char ch = tolower(name[i]);
181 int j, continue_from, len;
182
183 /* If the next character is a comma or a NULL then this is
184 * a request for the default Serial port
185 */
186 if (name[++i] == 0 || name[i] == ',') {
187 if (ch=='s')
188 sername=SERPORT1;
189 break;
190 }
191
192 /* Next character must be an = */
193 if (name[i] != '=') return 0;
194 /* Search for the end of the port spec. (ends in NULL or ,) */
195 for (j= ++i; name[j] != 0 && name[j] != ','; j++)
196 ; /* Do nothing */
197 /* Notice whether this is the last thing to parse or not
198 * and also calaculate the length of the string
199 */
200 if (name[j] == '0') continue_from = -1;
201 else continue_from = j;
202 len=(j-i);
203
204 /* And now try to match the serial / parallel port */
205 switch (ch) {
206 case 's': {
207 /* Match serial port */
208 if (len==1) {
209 if (name[i]=='1')
210 sername=SERPORT1;
211 else if (name[i]=='2')
212 sername=SERPORT2;
213 } else if (len==strlen(SERPORT1)) {
214 if (strncmp(name+i,SERPORT1,strlen(SERPORT1)) == 0)
215 sername=SERPORT1;
216 else if (strncmp(name+i,SERPORT2,strlen(SERPORT2)) == 0)
217 sername=SERPORT2;
218 }
219
220 break;
221 }
222
223 case 'h':
224 /* We don't actually deal with the H case here, we just
225 * match it and allow it through.
226 */
227 break;
228 }
229
230 if (continue_from == -1) return sername;
231 i = continue_from;
232 break;
233 }
234 }
235 } while (1);
236
237 return 0;
238 }
239
240
241 extern int Unix_IsSerialInUse(void)
242 {
243 if (serpfd >= 0)
244 return -1;
245
246 return 0;
247 }
248
249 extern int Unix_OpenSerial(const char *name)
250 {
251 #if defined(BSD) || defined(__CYGWIN__)
252 serpfd = open(name, O_RDWR);
253 #else
254 serpfd = open(name, O_RDWR | O_NONBLOCK);
255 #endif
256
257 if (serpfd < 0) {
258 perror("open");
259 return -1;
260 }
261 #ifdef TIOCEXCL
262 if (ioctl(serpfd, TIOCEXCL) < 0) {
263 close(serpfd);
264 perror("ioctl: TIOCEXCL");
265 return -1;
266 }
267 #endif
268
269 return 0;
270 }
271
272 extern void Unix_CloseSerial(void)
273 {
274 if (serpfd >= 0)
275 {
276 (void)close(serpfd);
277 serpfd = -1;
278 }
279 }
280
281 extern int Unix_ReadSerial(unsigned char *buf, int n, bool block)
282 {
283 fd_set fdset;
284 struct timeval tv;
285 int err;
286
287 FD_ZERO(&fdset);
288 FD_SET(serpfd, &fdset);
289
290 tv.tv_sec = 0;
291 tv.tv_usec = (block ? 10000 : 0);
292
293 err = select(serpfd + 1, &fdset, NULL, NULL, &tv);
294
295 if (err < 0 && errno != EINTR)
296 {
297 #ifdef DEBUG
298 perror("select");
299 #endif
300 panic("select failure");
301 return -1;
302 }
303 else if (err > 0 && FD_ISSET(serpfd, &fdset))
304 {
305 int s;
306
307 s = read(serpfd, buf, n);
308 if (s < 0)
309 perror("read:");
310 return s;
311 }
312 else /* err == 0 || FD_CLR(serpfd, &fdset) */
313 {
314 errno = ERRNO_FOR_BLOCKED_IO;
315 return -1;
316 }
317 }
318
319 extern int Unix_WriteSerial(unsigned char *buf, int n)
320 {
321 return write(serpfd, buf, n);
322 }
323
324 extern void Unix_ResetSerial(void)
325 {
326 struct termios terminfo;
327
328 tcgetattr(serpfd, &terminfo);
329 terminfo.c_lflag &= ~(ICANON | ISIG | ECHO | IEXTEN);
330 terminfo.c_iflag &= ~(IGNCR | INPCK | ISTRIP | ICRNL | BRKINT);
331 terminfo.c_iflag |= (IXON | IXOFF | IGNBRK);
332 terminfo.c_cflag = (terminfo.c_cflag & ~CSIZE) | CS8 | CREAD;
333 terminfo.c_cflag &= ~PARENB;
334 terminfo.c_cc[VMIN] = 1;
335 terminfo.c_cc[VTIME] = 0;
336 terminfo.c_oflag &= ~OPOST;
337 tcsetattr(serpfd, TCSAFLUSH, &terminfo);
338 }
339
340 extern void Unix_SetSerialBaudRate(int baudrate)
341 {
342 struct termios terminfo;
343
344 tcgetattr(serpfd, &terminfo);
345 cfsetospeed(&terminfo, baudrate);
346 cfsetispeed(&terminfo, baudrate);
347 tcsetattr(serpfd, TCSAFLUSH, &terminfo);
348 }
349
350 extern void Unix_ioctlNonBlocking(void)
351 {
352 #if defined(BSD)
353 int nonblockingIO = 1;
354 (void)ioctl(serpfd, FIONBIO, &nonblockingIO);
355
356 if (parpfd != -1)
357 (void)ioctl(parpfd, FIONBIO, &nonblockingIO);
358 #endif
359 }
360
361 extern void Unix_IsValidParallelDevice(
362 const char *portstring, char **sername, char **parname)
363 {
364 int i=0;
365 *sername=NULL;
366 *parname=NULL;
367
368 /* Do not recognise a NULL portstring */
369 if (portstring==NULL) return;
370
371 do {
372 switch (portstring[i]) {
373 case ',':
374 /* Skip over commas */
375 i++;
376 break;
377
378 default:
379 case 0:
380 /* End of string or bad characcter means we have finished */
381 return;
382
383 case 's':
384 case 'S':
385 case 'p':
386 case 'P':
387 case 'h':
388 case 'H': {
389 char ch = tolower(portstring[i]);
390 int j, continue_from, len;
391
392 /* If the next character is a comma or a NULL then this is
393 * a request for the default Serial or Parallel port
394 */
395 if (portstring[++i] == 0 || portstring[i] == ',') {
396 if (ch=='s') *sername=SERPORT1;
397 else if (ch=='p') *parname=PARPORT1;
398 break;
399 }
400
401 /* Next character must be an = */
402 if (portstring[i] != '=') return;
403 /* Search for the end of the port spec. (ends in NULL or ,) */
404 for (j= ++i; portstring[j] != 0 && portstring[j] != ','; j++)
405 ; /* Do nothing */
406 /* Notice whether this is the last thing to parse or not
407 * and also calaculate the length of the string
408 */
409 if (portstring[j] == '0') continue_from = -1;
410 else continue_from = j;
411 len=(j-i);
412
413 /* And now try to match the serial / parallel port */
414 switch (ch) {
415 case 's': {
416 /* Match serial port */
417 if (len==1) {
418 if (portstring[i]=='1') *sername=SERPORT1;
419 else if (portstring[i]=='2') *sername=SERPORT2;
420 } else if (len==strlen(SERPORT1)) {
421 if (strncmp(portstring+i,SERPORT1,strlen(SERPORT1)) == 0)
422 *sername=SERPORT1;
423 else if (strncmp(portstring+i,SERPORT2,strlen(SERPORT2)) == 0)
424 *sername=SERPORT2;
425 }
426 break;
427 }
428
429 case 'p': {
430 /* Match parallel port */
431 if (len==1) {
432 if (portstring[i]=='1') *parname=PARPORT1;
433 else if (portstring[i]=='2') *parname=PARPORT2;
434 } else if (len==strlen(PARPORT1)) {
435 if (strncmp(portstring+i,PARPORT1,strlen(PARPORT1)) == 0)
436 *parname=PARPORT1;
437 else if (strncmp(portstring+i,PARPORT2,strlen(PARPORT2)) == 0)
438 *parname=PARPORT2;
439 }
440 break;
441 }
442
443 case 'h':
444 /* We don't actually deal with the H case here, we just
445 * match it and allow it through.
446 */
447 break;
448 }
449
450 if (continue_from == -1) return;
451 i = continue_from;
452 break;
453 }
454 }
455 } while (1);
456 return; /* Will never get here */
457 }
458
459 extern int Unix_IsParallelInUse(void)
460 {
461 if (parpfd >= 0)
462 return -1;
463
464 return 0;
465 }
466
467 extern int Unix_OpenParallel(const char *name)
468 {
469 #if defined(BSD)
470 parpfd = open(name, O_RDWR);
471 #else
472 parpfd = open(name, O_RDWR | O_NONBLOCK);
473 #endif
474
475 if (parpfd < 0)
476 {
477 char errbuf[256];
478
479 sprintf(errbuf, "open %s", name);
480 perror(errbuf);
481
482 return -1;
483 }
484
485 return 0;
486 }
487
488 extern void Unix_CloseParallel(void)
489 {
490 if (parpfd >= 0)
491 {
492 (void)close(parpfd);
493 parpfd = -1;
494 }
495 }
496
497
498 extern unsigned int Unix_WriteParallel(unsigned char *buf, int n)
499 {
500 int ngone;
501
502 if ((ngone = write(parpfd, buf, n)) < 0)
503 {
504 /*
505 * we ignore errors (except for debug purposes)
506 */
507 #ifdef DEBUG
508 char errbuf[256];
509
510 sprintf(errbuf, "send_packet: write");
511 perror(errbuf);
512 #endif
513 ngone = 0;
514 }
515
516 /* finished */
517 return (unsigned int)ngone;
518 }
519
520
521 #ifdef sun
522 extern void Unix_ResetParallel(void)
523 {
524 struct bpp_transfer_parms tp;
525
526 #ifdef DEBUG
527 printf("serpar_reset\n");
528 #endif
529
530 /*
531 * we need to set the parallel port up for BUSY handshaking,
532 * and select the timeout
533 */
534 if (ioctl(parpfd, BPPIOC_GETPARMS, &tp) < 0)
535 {
536 #ifdef DEBUG
537 perror("ioctl(BPPIOCGETPARMS)");
538 #endif
539 panic("serpar_reset: cannot get BPP parameters");
540 }
541
542 tp.write_handshake = BPP_BUSY_HS;
543 tp.write_timeout = PP_TIMEOUT;
544
545 if (ioctl(parpfd, BPPIOC_SETPARMS, &tp) < 0)
546 {
547 #ifdef DEBUG
548 perror("ioctl(BPPIOC_SETPARMS)");
549 #endif
550 panic("serpar_reset: cannot set BPP parameters");
551 }
552 }
553
554 #else
555
556 /* Parallel not supported on HP */
557
558 extern void Unix_ResetParallel(void)
559 {
560 }
561
562 #endif
563