/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 1995 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /* * Do not include sys/conf.h- it isn't in the compatibility include dirs. */ #ifdef THIS_IS_AVAIL #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cdioctl.h" #include "s5dkio.h" #include "s5fdio.h" /* * parameter for windows ioctls */ struct winclip { int wc_blockbytes; /* size of wc_block */ int wc_clipid; /* Current clip id of clipping */ short wc_screenrect[4]; /* Screen relatived (used when paint) */ char *wc_block; /* Block where RectList is copied. */ }; /* * Ioctl control packet */ struct s5termios { tcflag_t c_iflag; /* input modes */ tcflag_t c_oflag; /* output modes */ tcflag_t c_cflag; /* control modes */ tcflag_t c_lflag; /* line discipline modes */ cc_t c_cc[19]; /* control chars */ }; #define N_ENOMSG 35 #define N_I_FIND ('S'<<8)|013 #define N_I_PUSH ('S'<<8)|02 #define WINGETEXPOSEDRL _IOWR('g',31,struct winclip) #define WINGETDAMAGEDRL _IOWR('g',32,struct winclip) struct n_sgttyb { char sg_ispeed; /* input speed */ char sg_ospeed; /* output speed */ char sg_erase; /* erase character */ char sg_kill; /* kill character */ int sg_flags; /* mode flags */ }; static int handle_dkio_partitions(int, int, int); static int tcget(int, int, int); static int tcset(int, int, int); static int _bc_ioctl(int, int, int); int ioctl(int des, int request, int arg) { int ret; if ((ret = _bc_ioctl(des, request, arg)) == -1) maperror(); return (ret); } int bc_ioctl(int des, int request, int arg) { int ret; if ((ret = _bc_ioctl(des, request, arg)) == -1) maperror(); return (ret); } static int _bc_ioctl(int des, int request, int arg) { int ret; int nreq = (request >> 8) & 0xFF; struct n_sgttyb nsg; struct s5_dk_cinfo newArgs; struct dk_info *infoArgs; struct dk_conf *confArgs; extern int errno; /* not all mappings for 'm' have been performed */ switch (nreq) { case ((int) 't'): if (_ioctl(des, N_I_FIND, "ttcompat") == 0) if (_ioctl(des, N_I_PUSH, "ttcompat") == -1) perror("ioctl/I_PUSH"); switch(request) { case TIOCSETD: /* added for sunview */ return(0); case TIOCREMOTE: request = ('t'<<8)|30; break; case TIOCNOTTY: bc_setsid(); return(0); case TIOCGPGRP: request = ('t'<<8)|20; break; case TIOCSPGRP: { pid_t pgid; sigset_t set, oset; request = ('t'<<8)|21; ret = _ioctl(des, request, arg); /* * SunOS4.x allows this to succeed * even if the process group does * not exist yet. We emulate the 4.x * bug by creating the process group * and reissuing the ioctl(). * See bugid 1175044. */ if (ret != 0 && errno == EPERM && (pgid = *((pid_t *)arg)) != 0 && pgid == getpid() && setpgid(0, pgid) == 0) { sigemptyset(&set); sigaddset(&set, SIGTSTP); sigaddset(&set, SIGTTIN); sigaddset(&set, SIGTTOU); sigprocmask(SIG_BLOCK, &set, &oset); ret = _ioctl(des, request, arg); sigprocmask(SIG_SETMASK, &oset, NULL); } return(ret); } case TIOCSTI: request = ('t'<<8)|23; break; case TIOCSIGNAL: request = ('t'<<8)|31; break; case TIOCCONS: request = ('t'<<8)|36; break; case TIOCSWINSZ: request = ('T'<<8)|103; break; case TIOCGWINSZ: request = ('T'<<8)|104; break; case TIOCSETP: case TIOCSETN: { struct sgttyb *sg = (struct sgttyb *)arg; nsg.sg_ispeed = sg->sg_ispeed; nsg.sg_ospeed = sg->sg_ospeed; nsg.sg_erase = sg->sg_erase; nsg.sg_kill = sg->sg_kill; nsg.sg_flags = (int)sg->sg_flags; arg = (int)&nsg; request = request & 0x0FFFF; break; } case TIOCGETP: { struct sgttyb *sg = (struct sgttyb *)arg; ret = _ioctl(des, request&0xFFFF, &nsg); if (ret != -1) { sg->sg_ispeed = nsg.sg_ispeed; sg->sg_ospeed = nsg.sg_ospeed; sg->sg_erase = nsg.sg_erase; sg->sg_kill = nsg.sg_kill; sg->sg_flags = (short)nsg.sg_flags & 0x0FFFF; } return(ret); } case TIOCPKT: case TIOCUCNTL: case TIOCTCNTL: case TIOCSSOFTCAR: case TIOCGSOFTCAR: case TIOCISPACE: case TIOCISIZE: case TIOCSSIZE: case TIOCGSIZE: break; default: request = request & 0x0FFFF; break; } break; case ((int) 'T'): switch(request) { case TCGETS: request = ('T'<<8)|13; return(tcget(des, request, arg)); break; case TCSETS: request = ('T'<<8)|14; return(tcset(des, request, arg)); break; case TCSETSW: request = ('T'<<8)|15; return(tcset(des, request, arg)); break; case TCSETSF: request = ('T'<<8)|16; return(tcset(des, request, arg)); break; case TCGETA: case TCSETA: case TCSETAW: case TCSETAF: default: request = request & 0x0FFFF; break; } break; case ((int) 'S'): switch (request) { case I_PLINK: request = ('S'<<8)|026; break; case I_PUNLINK: request = ('S'<<8)|027; break; case I_STR: { struct strioctl *iarg = (struct strioctl *)arg; int cmd = iarg->ic_cmd; switch (cmd) { case TI_GETINFO: { /* * The T_info_ack structure * has one additional word * added to it in 5.x. * To prevent the module from * overwritting user memory we * use an internal buffer for * the transfer and copy out * the results to the caller. */ struct { struct T_info_ack info; long pad[16]; } args; char *dp = iarg->ic_dp; memcpy(&args.info, iarg->ic_dp, sizeof(struct T_info_ack)); iarg->ic_dp = (char *) &args.info; iarg->ic_cmd = (TIMOD | 140); ret = _ioctl(des, request & 0xffff, arg); iarg->ic_cmd = cmd; iarg->ic_dp = dp; iarg->ic_len = sizeof(struct T_info_ack); memcpy(iarg->ic_dp, &args.info, iarg->ic_len); return (ret); break; } case TI_OPTMGMT: iarg->ic_cmd = (TIMOD | 141); break; case TI_BIND: iarg->ic_cmd = (TIMOD | 142); break; case TI_UNBIND: iarg->ic_cmd = (TIMOD | 143); break; } ret = _ioctl(des, request & 0xffff, arg); iarg->ic_cmd = cmd; return ret; } default: request = request & 0x0FFFF; break; } break; case ((int) 'm'): switch (request) { case MSIOGETPARMS: request = ('m'<<8)|1; break; case MSIOSETPARMS: request = ('m'<<8)|2; break; default: request = request & 0x0FFFF; break; } break; case ((int) 'd'): switch (request) { case DKIOCGGEOM: request = S5DKIOCGGEOM; break; case DKIOCSGEOM: request = S5DKIOCSGEOM; break; case DKIOCSAPART: request = S5DKIOCSAPART; break; case DKIOCGAPART: request = S5DKIOCGAPART; break; case DKIOCSTYPE: request = S5HDKIOCSTYPE; break; case DKIOCGTYPE: request = S5HDKIOCGTYPE; break; case DKIOCSBAD: request = S5HDKIOCSBAD; break; case DKIOCGBAD: request = S5HDKIOCGBAD; break; case DKIOCSCMD: request = S5HDKIOCSCMD; break; case DKIOCGDIAG: request = S5HDKIOCGDIAG; break; case FDKIOGCHAR: request = S5FDIOGCHAR; break; case FDKIOSCHAR: request = S5FDIOSCHAR; break; case FDKEJECT: request = S5FDEJECT; break; case FDKGETCHANGE: request = S5FDGETCHANGE; break; case FDKGETDRIVECHAR: request = S5FDGETDRIVECHAR; break; case FDKSETDRIVECHAR: request = S5FDSETDRIVECHAR; break; case FDKGETSEARCH: request = S5FDGETSEARCH; break; case FDKSETSEARCH: request = S5FDSETSEARCH; break; case FDKIOCSCMD: request = S5FDIOCMD; break; case F_RAW: request = S5FDRAW; break; case DKIOCINFO: ret = _ioctl(des, S5DKIOCINFO, &newArgs); if (ret != -1) { infoArgs = (struct dk_info *)arg; infoArgs->dki_ctlr = newArgs.dki_addr; infoArgs->dki_unit = newArgs.dki_unit; infoArgs->dki_ctype = newArgs.dki_ctype; infoArgs->dki_flags = newArgs.dki_flags; } return ret; break; case DKIOCGCONF: ret = _ioctl(des, S5DKIOCINFO, &newArgs); if (ret != -1) { confArgs = (struct dk_conf *)arg; strncpy(confArgs->dkc_cname, newArgs.dki_cname, DK_DEVLEN); strncpy(confArgs->dkc_dname, newArgs.dki_dname, DK_DEVLEN); confArgs->dkc_ctype = (u_short)newArgs.dki_ctype; confArgs->dkc_flags = (u_short)newArgs.dki_flags; confArgs->dkc_cnum = newArgs.dki_cnum; confArgs->dkc_addr = newArgs.dki_addr; confArgs->dkc_space = (u_int)newArgs.dki_space; confArgs->dkc_prio = newArgs.dki_prio; confArgs->dkc_vec = newArgs.dki_vec; confArgs->dkc_unit = newArgs.dki_unit; confArgs->dkc_slave = newArgs.dki_slave; } return ret; break; case DKIOCWCHK: /* * This is unsupported in SVR4. It * turns on verify-after-write for * the floppy. I don't think the * system call should fail, however. */ return 0; break; case DKIOCGPART: case DKIOCSPART: return (handle_dkio_partitions(des, request, arg)); case DKIOCGLOG: /* unsupported */ errno = EINVAL; return -1; break; case DESIOCBLOCK: case DESIOCQUICK: break; /* no change for these two */ default: request = request & 0x0FFFF; /* try */ break; } break; case ((int) 'c'): switch (request) { case CDROMPAUSE: request = S5CDROMPAUSE; break; case CDROMRESUME: request = S5CDROMRESUME; break; case CDROMPLAYMSF: request = S5CDROMPLAYMSF; break; case CDROMPLAYTRKIND: request = S5CDROMPLAYTRKIND; break; case CDROMREADTOCHDR: request = S5CDROMREADTOCHDR; break; case CDROMREADTOCENTRY: request = S5CDROMREADTOCENTRY; break; case CDROMSTOP: request = S5CDROMSTOP; break; case CDROMSTART: request = S5CDROMSTART; break; case CDROMEJECT: request = S5CDROMEJECT; break; case CDROMVOLCTRL: request = S5CDROMVOLCTRL; break; case CDROMSUBCHNL: request = S5CDROMSUBCHNL; break; case CDROMREADMODE1: request = S5CDROMREADMODE1; break; case CDROMREADMODE2: request = S5CDROMREADMODE2; break; } break; case ((int) 'u'): switch (request) { case USCSICMD: { struct s5_uscsi_cmd s5_cmd; struct uscsi_cmd *cmd = (struct uscsi_cmd *) arg; request = S5USCSICMD; s5_cmd.uscsi_cdb = cmd->uscsi_cdb; s5_cmd.uscsi_cdblen = cmd->uscsi_cdblen; s5_cmd.uscsi_bufaddr = cmd->uscsi_bufaddr; s5_cmd.uscsi_buflen = cmd->uscsi_buflen; s5_cmd.uscsi_flags = cmd->uscsi_flags; ret = _ioctl(des, request, &s5_cmd); cmd->uscsi_status = s5_cmd.uscsi_status; return(ret); } } break; case ((int) 'k'): case ((int) 'v'): case ((int) 'F'): case ((int) 'G'): case ((int) 'X'): case ((int) 'L'): request = request & 0x0FFFF; break; case ((int) 'f'): if ((request == FIOCLEX) || (request == FIONCLEX)) return(fcntl(des, F_SETFD, ((request == FIOCLEX) ? 1 : 0))); break; case ((int) 'g'): /* Treat the following 2 ioctls specially for * sunview. */ if (request == WINGETEXPOSEDRL || request == WINGETDAMAGEDRL) { ret = _ioctl(des, request, arg); if (errno == N_ENOMSG) errno = EFBIG; return(ret); } break; } return (_ioctl(des, request, arg)); } static int handle_dkio_partitions(int des, int request, int arg) { struct s5_dk_cinfo cinfo; struct dk_allmap map; struct dk_map *part; int ret; extern int errno; part = (struct dk_map *) arg; ret = _ioctl(des, S5DKIOCINFO, &cinfo); if ((cinfo.dki_partition < 0) || (cinfo.dki_partition >= NDKMAP)) { errno = EINVAL; return (-1); } if (ret != -1) { ret = _ioctl(des, S5DKIOCGAPART, &map); if (ret != -1) { if (request == DKIOCGPART) { part->dkl_cylno = map.dka_map[cinfo.dki_partition].dkl_cylno; part->dkl_nblk = map.dka_map[cinfo.dki_partition].dkl_nblk; } else { map.dka_map[cinfo.dki_partition].dkl_cylno = part->dkl_cylno; map.dka_map[cinfo.dki_partition].dkl_nblk = part->dkl_nblk; ret = _ioctl(des, S5DKIOCSAPART, &map); } } } return (ret); } static int tcset(des, request, arg) register int des; register int request; int arg; { struct s5termios s5termios; struct termios *termios; termios = (struct termios *)arg; if (termios != NULL) { s5termios.c_iflag = termios->c_iflag; s5termios.c_oflag = termios->c_oflag; s5termios.c_cflag = termios->c_cflag; s5termios.c_lflag = termios->c_lflag; memcpy(s5termios.c_cc, termios->c_cc, NCCS); return (_ioctl(des, request, &s5termios)); } else return (_ioctl(des, request, NULL)); } static int tcget(des, request, arg) register int des; register int request; int arg; { struct s5termios s5termios; struct termios *termios; int ret; termios = (struct termios *)arg; ret = _ioctl(des, request, &s5termios); if (termios != NULL) { termios->c_iflag = s5termios.c_iflag; termios->c_oflag = s5termios.c_oflag; termios->c_cflag = s5termios.c_cflag; termios->c_lflag = s5termios.c_lflag; memcpy(termios->c_cc, s5termios.c_cc, NCCS); } return (ret); }