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 1995 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
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
ioctl(int des,int request,int arg)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
bc_ioctl(int des,int request,int arg)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
_bc_ioctl(int des,int request,int arg)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
handle_dkio_partitions(int des,int request,int arg)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
tcset(des,request,arg)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
tcget(des,request,arg)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