1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1995, by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Do not include sys/conf.h- it isn't in the compatibility include dirs. 31 */ 32 #ifdef THIS_IS_AVAIL 33 #include <sys/conf.h> 34 #endif 35 #include <stdio.h> 36 #include <signal.h> 37 #include <sys/types.h> 38 #include <sys/ioccom.h> 39 #include <sys/stropts.h> 40 #include <sys/des.h> 41 #include <sys/fcntl.h> 42 #include <sys/filio.h> 43 #include <sys/termios.h> 44 #include <sys/termio.h> 45 #include <sys/ttold.h> 46 #include <sys/ttycom.h> 47 #include <sys/msio.h> 48 #include <sys/errno.h> 49 #include <nettli/tihdr.h> 50 #include <nettli/timod.h> 51 #include <nettli/tiuser.h> 52 #include <sun/dkio.h> 53 #include <scsi/impl/uscsi.h> 54 #include "cdioctl.h" 55 #include "s5dkio.h" 56 #include "s5fdio.h" 57 58 /* 59 * parameter for windows ioctls 60 */ 61 struct winclip { 62 int wc_blockbytes; /* size of wc_block */ 63 int wc_clipid; /* Current clip id of clipping */ 64 short wc_screenrect[4]; /* Screen relatived (used when paint) */ 65 char *wc_block; /* Block where RectList is copied. */ 66 }; 67 68 /* 69 * Ioctl control packet 70 */ 71 struct s5termios { 72 tcflag_t c_iflag; /* input modes */ 73 tcflag_t c_oflag; /* output modes */ 74 tcflag_t c_cflag; /* control modes */ 75 tcflag_t c_lflag; /* line discipline modes */ 76 cc_t c_cc[19]; /* control chars */ 77 }; 78 79 #define N_ENOMSG 35 80 #define N_I_FIND ('S'<<8)|013 81 #define N_I_PUSH ('S'<<8)|02 82 #define WINGETEXPOSEDRL _IOWR(g,31,struct winclip) 83 #define WINGETDAMAGEDRL _IOWR(g,32,struct winclip) 84 85 struct n_sgttyb { 86 char sg_ispeed; /* input speed */ 87 char sg_ospeed; /* output speed */ 88 char sg_erase; /* erase character */ 89 char sg_kill; /* kill character */ 90 int sg_flags; /* mode flags */ 91 }; 92 93 static int handle_dkio_partitions(int, int, int); 94 static int tcget(int, int, int); 95 static int tcset(int, int, int); 96 static int _bc_ioctl(int, int, int); 97 98 int 99 ioctl(int des, int request, int arg) 100 { 101 int ret; 102 103 if ((ret = _bc_ioctl(des, request, arg)) == -1) 104 maperror(); 105 return (ret); 106 } 107 108 int 109 bc_ioctl(int des, int request, int arg) 110 { 111 int ret; 112 113 if ((ret = _bc_ioctl(des, request, arg)) == -1) 114 maperror(); 115 return (ret); 116 } 117 118 static int 119 _bc_ioctl(int des, int request, int arg) 120 { 121 int ret; 122 int nreq = (request >> 8) & 0xFF; 123 struct n_sgttyb nsg; 124 struct s5_dk_cinfo newArgs; 125 struct dk_info *infoArgs; 126 struct dk_conf *confArgs; 127 extern int errno; 128 129 /* not all mappings for 'm' have been performed */ 130 switch (nreq) { 131 case ((int) 't'): 132 if (_ioctl(des, N_I_FIND, "ttcompat") == 0) 133 if (_ioctl(des, N_I_PUSH, "ttcompat") == -1) 134 perror("ioctl/I_PUSH"); 135 switch(request) { 136 case TIOCSETD: 137 /* added for sunview */ 138 return(0); 139 case TIOCREMOTE: request = ('t'<<8)|30; 140 break; 141 case TIOCNOTTY: 142 bc_setsid(); 143 return(0); 144 case TIOCGPGRP: request = ('t'<<8)|20; 145 break; 146 case TIOCSPGRP: 147 { 148 pid_t pgid; 149 sigset_t set, oset; 150 151 request = ('t'<<8)|21; 152 ret = _ioctl(des, request, arg); 153 154 /* 155 * SunOS4.x allows this to succeed 156 * even if the process group does 157 * not exist yet. We emulate the 4.x 158 * bug by creating the process group 159 * and reissuing the ioctl(). 160 * See bugid 1175044. 161 */ 162 if (ret != 0 && errno == EPERM && 163 (pgid = *((pid_t *)arg)) != 0 && 164 pgid == getpid() && 165 setpgid(0, pgid) == 0) { 166 sigemptyset(&set); 167 sigaddset(&set, SIGTSTP); 168 sigaddset(&set, SIGTTIN); 169 sigaddset(&set, SIGTTOU); 170 sigprocmask(SIG_BLOCK, 171 &set, &oset); 172 ret = _ioctl(des, 173 request, arg); 174 sigprocmask(SIG_SETMASK, 175 &oset, NULL); 176 } 177 return(ret); 178 } 179 case TIOCSTI: request = ('t'<<8)|23; 180 break; 181 case TIOCSIGNAL: request = ('t'<<8)|31; 182 break; 183 case TIOCCONS: request = ('t'<<8)|36; 184 break; 185 case TIOCSWINSZ: request = ('T'<<8)|103; 186 break; 187 case TIOCGWINSZ: request = ('T'<<8)|104; 188 break; 189 case TIOCSETP: 190 case TIOCSETN: 191 { 192 struct sgttyb *sg = (struct sgttyb *)arg; 193 nsg.sg_ispeed = sg->sg_ispeed; 194 nsg.sg_ospeed = sg->sg_ospeed; 195 nsg.sg_erase = sg->sg_erase; 196 nsg.sg_kill = sg->sg_kill; 197 nsg.sg_flags = (int)sg->sg_flags; 198 arg = (int)&nsg; 199 request = request & 0x0FFFF; 200 break; 201 } 202 203 case TIOCGETP: 204 { 205 struct sgttyb *sg = (struct sgttyb *)arg; 206 207 ret = _ioctl(des, request&0xFFFF, &nsg); 208 if (ret != -1) { 209 sg->sg_ispeed = nsg.sg_ispeed; 210 sg->sg_ospeed = nsg.sg_ospeed; 211 sg->sg_erase = nsg.sg_erase; 212 sg->sg_kill = nsg.sg_kill; 213 sg->sg_flags = (short)nsg.sg_flags & 0x0FFFF; 214 } 215 return(ret); 216 } 217 case TIOCPKT: 218 case TIOCUCNTL: 219 case TIOCTCNTL: 220 case TIOCSSOFTCAR: 221 case TIOCGSOFTCAR: 222 case TIOCISPACE: 223 case TIOCISIZE: 224 case TIOCSSIZE: 225 case TIOCGSIZE: 226 break; 227 default: request = request & 0x0FFFF; 228 break; 229 } 230 break; 231 case ((int) 'T'): 232 switch(request) { 233 case TCGETS: 234 request = ('T'<<8)|13; 235 return(tcget(des, request, arg)); 236 break; 237 case TCSETS: 238 request = ('T'<<8)|14; 239 return(tcset(des, request, arg)); 240 break; 241 case TCSETSW: 242 request = ('T'<<8)|15; 243 return(tcset(des, request, arg)); 244 break; 245 case TCSETSF: 246 request = ('T'<<8)|16; 247 return(tcset(des, request, arg)); 248 break; 249 case TCGETA: 250 case TCSETA: 251 case TCSETAW: 252 case TCSETAF: 253 default: 254 request = request & 0x0FFFF; 255 break; 256 } 257 break; 258 case ((int) 'S'): 259 switch (request) { 260 case I_PLINK: request = ('S'<<8)|026; 261 break; 262 case I_PUNLINK: request = ('S'<<8)|027; 263 break; 264 case I_STR: { 265 struct strioctl *iarg = 266 (struct strioctl *)arg; 267 int cmd = iarg->ic_cmd; 268 269 switch (cmd) { 270 case TI_GETINFO: { 271 /* 272 * The T_info_ack structure 273 * has one additional word 274 * added to it in 5.x. 275 * To prevent the module from 276 * overwritting user memory we 277 * use an internal buffer for 278 * the transfer and copy out 279 * the results to the caller. 280 */ 281 struct { 282 struct T_info_ack info; 283 long pad[16]; 284 } args; 285 char *dp = iarg->ic_dp; 286 287 memcpy(&args.info, iarg->ic_dp, 288 sizeof(struct T_info_ack)); 289 iarg->ic_dp = 290 (char *) &args.info; 291 iarg->ic_cmd = (TIMOD | 140); 292 ret = _ioctl(des, 293 request & 0xffff, arg); 294 iarg->ic_cmd = cmd; 295 iarg->ic_dp = dp; 296 iarg->ic_len = 297 sizeof(struct T_info_ack); 298 memcpy(iarg->ic_dp, &args.info, 299 iarg->ic_len); 300 return (ret); 301 break; 302 } 303 case TI_OPTMGMT: 304 iarg->ic_cmd = (TIMOD | 141); 305 break; 306 case TI_BIND: 307 iarg->ic_cmd = (TIMOD | 142); 308 break; 309 case TI_UNBIND: 310 iarg->ic_cmd = (TIMOD | 143); 311 break; 312 } 313 ret = _ioctl(des, 314 request & 0xffff, arg); 315 iarg->ic_cmd = cmd; 316 return ret; 317 } 318 default: request = request & 0x0FFFF; 319 break; 320 } 321 break; 322 case ((int) 'm'): 323 switch (request) { 324 case MSIOGETPARMS: request = ('m'<<8)|1; 325 break; 326 case MSIOSETPARMS: request = ('m'<<8)|2; 327 break; 328 default: request = request & 0x0FFFF; 329 break; 330 } 331 break; 332 case ((int) 'd'): 333 switch (request) { 334 case DKIOCGGEOM: 335 request = S5DKIOCGGEOM; 336 break; 337 case DKIOCSGEOM: 338 request = S5DKIOCSGEOM; 339 break; 340 case DKIOCSAPART: 341 request = S5DKIOCSAPART; 342 break; 343 case DKIOCGAPART: 344 request = S5DKIOCGAPART; 345 break; 346 case DKIOCSTYPE: 347 request = S5HDKIOCSTYPE; 348 break; 349 case DKIOCGTYPE: 350 request = S5HDKIOCGTYPE; 351 break; 352 case DKIOCSBAD: 353 request = S5HDKIOCSBAD; 354 break; 355 case DKIOCGBAD: 356 request = S5HDKIOCGBAD; 357 break; 358 case DKIOCSCMD: 359 request = S5HDKIOCSCMD; 360 break; 361 case DKIOCGDIAG: 362 request = S5HDKIOCGDIAG; 363 break; 364 case FDKIOGCHAR: 365 request = S5FDIOGCHAR; 366 break; 367 case FDKIOSCHAR: 368 request = S5FDIOSCHAR; 369 break; 370 case FDKEJECT: 371 request = S5FDEJECT; 372 break; 373 case FDKGETCHANGE: 374 request = S5FDGETCHANGE; 375 break; 376 case FDKGETDRIVECHAR: 377 request = S5FDGETDRIVECHAR; 378 break; 379 case FDKSETDRIVECHAR: 380 request = S5FDSETDRIVECHAR; 381 break; 382 case FDKGETSEARCH: 383 request = S5FDGETSEARCH; 384 break; 385 case FDKSETSEARCH: 386 request = S5FDSETSEARCH; 387 break; 388 case FDKIOCSCMD: 389 request = S5FDIOCMD; 390 break; 391 case F_RAW: 392 request = S5FDRAW; 393 break; 394 case DKIOCINFO: 395 ret = _ioctl(des, S5DKIOCINFO, &newArgs); 396 if (ret != -1) { 397 infoArgs = (struct dk_info *)arg; 398 infoArgs->dki_ctlr = 399 newArgs.dki_addr; 400 infoArgs->dki_unit = 401 newArgs.dki_unit; 402 infoArgs->dki_ctype = 403 newArgs.dki_ctype; 404 infoArgs->dki_flags = 405 newArgs.dki_flags; 406 } 407 return ret; 408 break; 409 case DKIOCGCONF: 410 ret = _ioctl(des, S5DKIOCINFO, &newArgs); 411 if (ret != -1) { 412 confArgs = (struct dk_conf *)arg; 413 strncpy(confArgs->dkc_cname, 414 newArgs.dki_cname, 415 DK_DEVLEN); 416 strncpy(confArgs->dkc_dname, 417 newArgs.dki_dname, 418 DK_DEVLEN); 419 confArgs->dkc_ctype = 420 (u_short)newArgs.dki_ctype; 421 confArgs->dkc_flags = 422 (u_short)newArgs.dki_flags; 423 confArgs->dkc_cnum = 424 newArgs.dki_cnum; 425 confArgs->dkc_addr = 426 newArgs.dki_addr; 427 confArgs->dkc_space = 428 (u_int)newArgs.dki_space; 429 confArgs->dkc_prio = 430 newArgs.dki_prio; 431 confArgs->dkc_vec = 432 newArgs.dki_vec; 433 confArgs->dkc_unit = 434 newArgs.dki_unit; 435 confArgs->dkc_slave = 436 newArgs.dki_slave; 437 } 438 return ret; 439 break; 440 case DKIOCWCHK: 441 /* 442 * This is unsupported in SVR4. It 443 * turns on verify-after-write for 444 * the floppy. I don't think the 445 * system call should fail, however. 446 */ 447 return 0; 448 break; 449 case DKIOCGPART: 450 case DKIOCSPART: 451 return (handle_dkio_partitions(des, 452 request, arg)); 453 case DKIOCGLOG: 454 /* unsupported */ 455 errno = EINVAL; 456 return -1; 457 break; 458 case DESIOCBLOCK: 459 case DESIOCQUICK: 460 break; /* no change for these two */ 461 default: 462 request = request & 0x0FFFF; /* try */ 463 break; 464 } 465 break; 466 case ((int) 'c'): 467 switch (request) { 468 case CDROMPAUSE: 469 request = S5CDROMPAUSE; 470 break; 471 case CDROMRESUME: 472 request = S5CDROMRESUME; 473 break; 474 case CDROMPLAYMSF: 475 request = S5CDROMPLAYMSF; 476 break; 477 case CDROMPLAYTRKIND: 478 request = S5CDROMPLAYTRKIND; 479 break; 480 case CDROMREADTOCHDR: 481 request = S5CDROMREADTOCHDR; 482 break; 483 case CDROMREADTOCENTRY: 484 request = S5CDROMREADTOCENTRY; 485 break; 486 case CDROMSTOP: 487 request = S5CDROMSTOP; 488 break; 489 case CDROMSTART: 490 request = S5CDROMSTART; 491 break; 492 case CDROMEJECT: 493 request = S5CDROMEJECT; 494 break; 495 case CDROMVOLCTRL: 496 request = S5CDROMVOLCTRL; 497 break; 498 case CDROMSUBCHNL: 499 request = S5CDROMSUBCHNL; 500 break; 501 case CDROMREADMODE1: 502 request = S5CDROMREADMODE1; 503 break; 504 case CDROMREADMODE2: 505 request = S5CDROMREADMODE2; 506 break; 507 } 508 break; 509 case ((int) 'u'): 510 switch (request) { 511 case USCSICMD: 512 { 513 struct s5_uscsi_cmd s5_cmd; 514 struct uscsi_cmd *cmd = 515 (struct uscsi_cmd *) arg; 516 request = S5USCSICMD; 517 s5_cmd.uscsi_cdb = cmd->uscsi_cdb; 518 s5_cmd.uscsi_cdblen = 519 cmd->uscsi_cdblen; 520 s5_cmd.uscsi_bufaddr = 521 cmd->uscsi_bufaddr; 522 s5_cmd.uscsi_buflen = 523 cmd->uscsi_buflen; 524 s5_cmd.uscsi_flags = 525 cmd->uscsi_flags; 526 ret = _ioctl(des, request, &s5_cmd); 527 cmd->uscsi_status = s5_cmd.uscsi_status; 528 return(ret); 529 } 530 } 531 break; 532 case ((int) 'k'): 533 case ((int) 'v'): 534 case ((int) 'F'): 535 case ((int) 'G'): 536 case ((int) 'X'): 537 case ((int) 'L'): 538 request = request & 0x0FFFF; 539 break; 540 case ((int) 'f'): 541 if ((request == FIOCLEX) || (request == FIONCLEX)) 542 return(fcntl(des, F_SETFD, 543 ((request == FIOCLEX) ? 1 : 0))); 544 break; 545 case ((int) 'g'): 546 /* Treat the following 2 ioctls specially for 547 * sunview. */ 548 if (request == WINGETEXPOSEDRL || 549 request == WINGETDAMAGEDRL) { 550 ret = _ioctl(des, request, arg); 551 if (errno == N_ENOMSG) 552 errno = EFBIG; 553 return(ret); 554 } 555 break; 556 } 557 return (_ioctl(des, request, arg)); 558 } 559 560 561 static int 562 handle_dkio_partitions(int des, int request, int arg) 563 { 564 struct s5_dk_cinfo cinfo; 565 struct dk_allmap map; 566 struct dk_map *part; 567 int ret; 568 extern int errno; 569 570 part = (struct dk_map *) arg; 571 572 ret = _ioctl(des, S5DKIOCINFO, &cinfo); 573 574 if ((cinfo.dki_partition < 0) || (cinfo.dki_partition >= NDKMAP)) { 575 errno = EINVAL; 576 return (-1); 577 } 578 579 if (ret != -1) { 580 ret = _ioctl(des, S5DKIOCGAPART, &map); 581 if (ret != -1) { 582 if (request == DKIOCGPART) { 583 part->dkl_cylno = 584 map.dka_map[cinfo.dki_partition].dkl_cylno; 585 part->dkl_nblk = 586 map.dka_map[cinfo.dki_partition].dkl_nblk; 587 } else { 588 map.dka_map[cinfo.dki_partition].dkl_cylno = 589 part->dkl_cylno; 590 map.dka_map[cinfo.dki_partition].dkl_nblk = 591 part->dkl_nblk; 592 ret = _ioctl(des, S5DKIOCSAPART, &map); 593 } 594 } 595 } 596 return (ret); 597 } 598 599 static int 600 tcset(des, request, arg) 601 register int des; 602 register int request; 603 int arg; 604 { 605 struct s5termios s5termios; 606 struct termios *termios; 607 608 termios = (struct termios *)arg; 609 610 if (termios != NULL) { 611 s5termios.c_iflag = termios->c_iflag; 612 s5termios.c_oflag = termios->c_oflag; 613 s5termios.c_cflag = termios->c_cflag; 614 s5termios.c_lflag = termios->c_lflag; 615 memcpy(s5termios.c_cc, termios->c_cc, NCCS); 616 return (_ioctl(des, request, &s5termios)); 617 } else 618 return (_ioctl(des, request, NULL)); 619 620 } 621 622 static int 623 tcget(des, request, arg) 624 register int des; 625 register int request; 626 int arg; 627 { 628 struct s5termios s5termios; 629 struct termios *termios; 630 int ret; 631 632 termios = (struct termios *)arg; 633 634 ret = _ioctl(des, request, &s5termios); 635 636 if (termios != NULL) { 637 termios->c_iflag = s5termios.c_iflag; 638 termios->c_oflag = s5termios.c_oflag; 639 termios->c_cflag = s5termios.c_cflag; 640 termios->c_lflag = s5termios.c_lflag; 641 memcpy(termios->c_cc, s5termios.c_cc, NCCS); 642 } 643 644 return (ret); 645 } 646