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: 1.3 $ 12 * $Date: 2004/12/27 14:00:54 $ 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 564