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