ioctl.c revision 722:636b850d4ee9
150472Speter/*
233975Sjdp * CDDL HEADER START
333975Sjdp *
433975Sjdp * The contents of this file are subject to the terms of the
533975Sjdp * Common Development and Distribution License, Version 1.0 only
633975Sjdp * (the "License").  You may not use this file except in compliance
784906Sobrien * with the License.
8218822Sdim *
9130575Sobrien * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1084906Sobrien * or http://www.opensolaris.org/os/licensing.
11136910Sru * See the License for the specific language governing permissions
1233975Sjdp * and limitations under the License.
1352924Sjb *
1452924Sjb * When distributing Covered Code, include this CDDL HEADER in each
1552924Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1652924Sjb * If applicable, add the following below this CDDL HEADER, with the
1784906Sobrien * fields enclosed by brackets "[]" replaced with your own identifying
1884906Sobrien * information: Portions Copyright [yyyy] [name of copyright owner]
1984906Sobrien *
2052924Sjb * CDDL HEADER END
2152924Sjb */
2233975Sjdp/*
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 */
61struct 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 */
71struct 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
85struct 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
93static int handle_dkio_partitions(int, int, int);
94static int tcget(int, int, int);
95static int tcset(int, int, int);
96static int _bc_ioctl(int, int, int);
97
98int
99ioctl(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
108int
109bc_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
118static 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
561static int
562handle_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
599static int
600tcset(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
622static int
623tcget(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