root/dev/wscons/wsdisplay_compat_usl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usl_sync_init
  2. usl_sync_done
  3. usl_sync_check
  4. usl_sync_get
  5. usl_detachproc
  6. usl_detachack
  7. usl_detachtimeout
  8. usl_attachproc
  9. usl_attachack
  10. usl_attachtimeout
  11. wsdisplay_usl_ioctl1
  12. wsdisplay_usl_ioctl2

    1 /* $OpenBSD: wsdisplay_compat_usl.c,v 1.19 2007/02/14 01:12:16 jsg Exp $ */
    2 /* $NetBSD: wsdisplay_compat_usl.c,v 1.12 2000/03/23 07:01:47 thorpej Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1998
    6  *      Matthias Drochner.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  */
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/timeout.h>
   33 #include <sys/ioctl.h>
   34 #include <sys/kernel.h>
   35 #include <sys/proc.h>
   36 #include <sys/signalvar.h>
   37 #include <sys/malloc.h>
   38 #include <sys/errno.h>
   39 
   40 #include <dev/wscons/wsconsio.h>
   41 #include <dev/wscons/wsdisplayvar.h>
   42 #include <dev/wscons/wscons_callbacks.h>
   43 #include <dev/wscons/wsdisplay_usl_io.h>
   44 
   45 #ifdef WSDISPLAY_DEBUG
   46 #define DPRINTF(x)       if (wsdisplaydebug) printf x
   47 int     wsdisplaydebug = 0;
   48 #else
   49 #define DPRINTF(x)
   50 #endif
   51 
   52 struct usl_syncdata {
   53         struct wsscreen *s_scr;
   54         struct proc *s_proc;
   55         pid_t s_pid;
   56         int s_flags;
   57 #define SF_DETACHPENDING 1
   58 #define SF_ATTACHPENDING 2
   59         int s_acqsig, s_relsig;
   60         int s_frsig; /* unused */
   61         void (*s_callback)(void *, int, int);
   62         void *s_cbarg;
   63         struct timeout s_attach_ch;
   64         struct timeout s_detach_ch;
   65 };
   66 
   67 int usl_sync_init(struct wsscreen *, struct usl_syncdata **,
   68                        struct proc *, int, int, int);
   69 void usl_sync_done(struct usl_syncdata *);
   70 int usl_sync_check(struct usl_syncdata *);
   71 struct usl_syncdata *usl_sync_get(struct wsscreen *);
   72 
   73 int usl_detachproc(void *, int, void (*)(void *, int, int), void *);
   74 int usl_detachack(struct usl_syncdata *, int);
   75 void usl_detachtimeout(void *);
   76 int usl_attachproc(void *, int, void (*)(void *, int, int), void *);
   77 int usl_attachack(struct usl_syncdata *, int);
   78 void usl_attachtimeout(void *);
   79 
   80 static const struct wscons_syncops usl_syncops = {
   81         usl_detachproc,
   82         usl_attachproc,
   83 #define _usl_sync_check ((int (*)(void *))usl_sync_check)
   84         _usl_sync_check,
   85 #define _usl_sync_destroy ((void (*)(void *))usl_sync_done)
   86         _usl_sync_destroy
   87 };
   88 
   89 #ifndef WSCOMPAT_USL_SYNCTIMEOUT
   90 #define WSCOMPAT_USL_SYNCTIMEOUT 5 /* seconds */
   91 #endif
   92 static int wscompat_usl_synctimeout = WSCOMPAT_USL_SYNCTIMEOUT;
   93 
   94 int
   95 usl_sync_init(scr, sdp, p, acqsig, relsig, frsig)
   96         struct wsscreen *scr;
   97         struct usl_syncdata **sdp;
   98         struct proc *p;
   99         int acqsig, relsig, frsig;
  100 {
  101         struct usl_syncdata *sd;
  102         int res;
  103 
  104         if (acqsig <= 0 || acqsig >= NSIG || relsig <= 0 || relsig >= NSIG ||
  105             frsig <= 0 || frsig >= NSIG)
  106                 return (EINVAL);
  107         sd = malloc(sizeof(struct usl_syncdata), M_DEVBUF, M_NOWAIT);
  108         if (!sd)
  109                 return (ENOMEM);
  110         sd->s_scr = scr;
  111         sd->s_proc = p;
  112         sd->s_pid = p->p_pid;
  113         sd->s_flags = 0;
  114         sd->s_acqsig = acqsig;
  115         sd->s_relsig = relsig;
  116         sd->s_frsig = frsig;
  117         timeout_set(&sd->s_attach_ch, usl_attachtimeout, sd);
  118         timeout_set(&sd->s_detach_ch, usl_detachtimeout, sd);
  119         res = wsscreen_attach_sync(scr, &usl_syncops, sd);
  120         if (res) {
  121                 free(sd, M_DEVBUF);
  122                 return (res);
  123         }
  124         *sdp = sd;
  125         return (0);
  126 }
  127 
  128 void
  129 usl_sync_done(sd)
  130         struct usl_syncdata *sd;
  131 {
  132         if (sd->s_flags & SF_DETACHPENDING) {
  133                 timeout_del(&sd->s_detach_ch);
  134                 (*sd->s_callback)(sd->s_cbarg, 0, 0);
  135         }
  136         if (sd->s_flags & SF_ATTACHPENDING) {
  137                 timeout_del(&sd->s_attach_ch);
  138                 (*sd->s_callback)(sd->s_cbarg, ENXIO, 0);
  139         }
  140         wsscreen_detach_sync(sd->s_scr);
  141         free(sd, M_DEVBUF);
  142 }
  143 
  144 int
  145 usl_sync_check(sd)
  146         struct usl_syncdata *sd;
  147 {
  148         if (sd->s_proc == pfind(sd->s_pid))
  149                 return (1);
  150         DPRINTF(("usl_sync_check: process %d died\n", sd->s_pid));
  151         usl_sync_done(sd);
  152         return (0);
  153 }
  154 
  155 struct usl_syncdata *
  156 usl_sync_get(scr)
  157         struct wsscreen *scr;
  158 {
  159         struct usl_syncdata *sd;
  160 
  161         if (wsscreen_lookup_sync(scr, &usl_syncops, (void **)&sd))
  162                 return (0);
  163         return (sd);
  164 }
  165 
  166 int
  167 usl_detachproc(cookie, waitok, callback, cbarg)
  168         void *cookie;
  169         int waitok;
  170         void (*callback)(void *, int, int);
  171         void *cbarg;
  172 {
  173         struct usl_syncdata *sd = cookie;
  174 
  175         if (!usl_sync_check(sd))
  176                 return (0);
  177 
  178         /* we really need a callback */
  179         if (!callback)
  180                 return (EINVAL);
  181 
  182         /*
  183          * Normally, this is called from the controlling process.
  184          * It is supposed to reply with a VT_RELDISP ioctl(), so
  185          * it is not useful to tsleep() here.
  186          */
  187         sd->s_callback = callback;
  188         sd->s_cbarg = cbarg;
  189         sd->s_flags |= SF_DETACHPENDING;
  190         psignal(sd->s_proc, sd->s_relsig);
  191         timeout_add(&sd->s_detach_ch, wscompat_usl_synctimeout * hz);
  192 
  193         return (EAGAIN);
  194 }
  195 
  196 int
  197 usl_detachack(sd, ack)
  198         struct usl_syncdata *sd;
  199         int ack;
  200 {
  201         if (!(sd->s_flags & SF_DETACHPENDING)) {
  202                 DPRINTF(("usl_detachack: not detaching\n"));
  203                 return (EINVAL);
  204         }
  205 
  206         timeout_del(&sd->s_detach_ch);
  207         sd->s_flags &= ~SF_DETACHPENDING;
  208 
  209         if (sd->s_callback)
  210                 (*sd->s_callback)(sd->s_cbarg, (ack ? 0 : EIO), 1);
  211 
  212         return (0);
  213 }
  214 
  215 void
  216 usl_detachtimeout(arg)
  217         void *arg;
  218 {
  219         struct usl_syncdata *sd = arg;
  220 
  221         DPRINTF(("usl_detachtimeout\n"));
  222 
  223         if (!(sd->s_flags & SF_DETACHPENDING)) {
  224                 DPRINTF(("usl_detachtimeout: not detaching\n"));
  225                 return;
  226         }
  227 
  228         sd->s_flags &= ~SF_DETACHPENDING;
  229 
  230         if (sd->s_callback)
  231                 (*sd->s_callback)(sd->s_cbarg, EIO, 0);
  232 
  233         (void) usl_sync_check(sd);
  234 }
  235 
  236 int
  237 usl_attachproc(cookie, waitok, callback, cbarg)
  238         void *cookie;
  239         int waitok;
  240         void (*callback)(void *, int, int);
  241         void *cbarg;
  242 {
  243         struct usl_syncdata *sd = cookie;
  244 
  245         if (!usl_sync_check(sd))
  246                 return (0);
  247 
  248         /* we really need a callback */
  249         if (!callback)
  250                 return (EINVAL);
  251 
  252         sd->s_callback = callback;
  253         sd->s_cbarg = cbarg;
  254         sd->s_flags |= SF_ATTACHPENDING;
  255         psignal(sd->s_proc, sd->s_acqsig);
  256         timeout_add(&sd->s_attach_ch, wscompat_usl_synctimeout * hz);
  257 
  258         return (EAGAIN);
  259 }
  260 
  261 int
  262 usl_attachack(sd, ack)
  263         struct usl_syncdata *sd;
  264         int ack;
  265 {
  266         if (!(sd->s_flags & SF_ATTACHPENDING)) {
  267                 DPRINTF(("usl_attachack: not attaching\n"));
  268                 return (EINVAL);
  269         }
  270 
  271         timeout_del(&sd->s_attach_ch);
  272         sd->s_flags &= ~SF_ATTACHPENDING;
  273 
  274         if (sd->s_callback)
  275                 (*sd->s_callback)(sd->s_cbarg, (ack ? 0 : EIO), 1);
  276 
  277         return (0);
  278 }
  279 
  280 void
  281 usl_attachtimeout(arg)
  282         void *arg;
  283 {
  284         struct usl_syncdata *sd = arg;
  285 
  286         DPRINTF(("usl_attachtimeout\n"));
  287 
  288         if (!(sd->s_flags & SF_ATTACHPENDING)) {
  289                 DPRINTF(("usl_attachtimeout: not attaching\n"));
  290                 return;
  291         }
  292 
  293         sd->s_flags &= ~SF_ATTACHPENDING;
  294 
  295         if (sd->s_callback)
  296                 (*sd->s_callback)(sd->s_cbarg, EIO, 0);
  297 
  298         (void) usl_sync_check(sd);
  299 }
  300 
  301 int
  302 wsdisplay_usl_ioctl1(sc, cmd, data, flag, p)
  303         struct wsdisplay_softc *sc;
  304         u_long cmd;
  305         caddr_t data;
  306         int flag;
  307         struct proc *p;
  308 {
  309         int idx, maxidx;
  310 
  311         switch (cmd) {
  312             case VT_OPENQRY:
  313                 maxidx = wsdisplay_maxscreenidx(sc);
  314                 for (idx = 0; idx <= maxidx; idx++) {
  315                         if (wsdisplay_screenstate(sc, idx) == 0) {
  316                                 *(int *)data = idx + 1;
  317                                 return (0);
  318                         }
  319                 }
  320                 return (ENXIO);
  321             case VT_GETACTIVE:
  322                 idx = wsdisplay_getactivescreen(sc);
  323                 *(int *)data = idx + 1;
  324                 return (0);
  325             case VT_ACTIVATE:
  326                 idx = *(int *)data - 1;
  327                 if (idx < 0)
  328                         return (EINVAL);
  329                 return (wsdisplay_switch((struct device *)sc, idx, 1));
  330             case VT_WAITACTIVE:
  331                 idx = *(int *)data - 1;
  332                 if (idx < 0)
  333                         return (EINVAL);
  334                 return (wsscreen_switchwait(sc, idx));
  335             case VT_GETSTATE:
  336 #define ss ((struct vt_stat *)data)
  337                 idx = wsdisplay_getactivescreen(sc);
  338                 ss->v_active = idx + 1;
  339                 ss->v_state = 0;
  340                 maxidx = wsdisplay_maxscreenidx(sc);
  341                 for (idx = 0; idx <= maxidx; idx++)
  342                         if (wsdisplay_screenstate(sc, idx) == EBUSY)
  343                                 ss->v_state |= (1 << (idx + 1));
  344 #undef ss
  345                 return (0);
  346 
  347 #ifdef WSDISPLAY_COMPAT_PCVT
  348             case VGAPCVTID:
  349 #define id ((struct pcvtid *)data)
  350                 strlcpy(id->name, "pcvt", sizeof id->name);
  351                 id->rmajor = 3;
  352                 id->rminor = 32;
  353 #undef id
  354                 return (0);
  355 #endif
  356 #ifdef WSDISPLAY_COMPAT_SYSCONS
  357             case CONS_GETVERS:
  358                 *(int *)data = 0x200;    /* version 2.0 */
  359                 return (0);
  360 #endif
  361 
  362             default:
  363                 return (-1);
  364         }
  365 
  366         return (0);
  367 }
  368 
  369 int
  370 wsdisplay_usl_ioctl2(sc, scr, cmd, data, flag, p)
  371         struct wsdisplay_softc *sc;
  372         struct wsscreen *scr;
  373         u_long cmd;
  374         caddr_t data;
  375         int flag;
  376         struct proc *p;
  377 {
  378         int intarg, res;
  379         u_long req;
  380         void *arg;
  381         struct usl_syncdata *sd;
  382         struct wskbd_bell_data bd;
  383 
  384         switch (cmd) {
  385             case VT_SETMODE:
  386 #define newmode ((struct vt_mode *)data)
  387                 if (newmode->mode == VT_PROCESS) {
  388                         res = usl_sync_init(scr, &sd, p, newmode->acqsig,
  389                                             newmode->relsig, newmode->frsig);
  390                         if (res)
  391                                 return (res);
  392                 } else {
  393                         sd = usl_sync_get(scr);
  394                         if (sd)
  395                                 usl_sync_done(sd);
  396                 }
  397 #undef newmode
  398                 return (0);
  399             case VT_GETMODE:
  400 #define cmode ((struct vt_mode *)data)
  401                 sd = usl_sync_get(scr);
  402                 if (sd) {
  403                         cmode->mode = VT_PROCESS;
  404                         cmode->relsig = sd->s_relsig;
  405                         cmode->acqsig = sd->s_acqsig;
  406                         cmode->frsig = sd->s_frsig;
  407                 } else
  408                         cmode->mode = VT_AUTO;
  409 #undef cmode
  410                 return (0);
  411             case VT_RELDISP:
  412 #define d (*(int *)data)
  413                 sd = usl_sync_get(scr);
  414                 if (!sd)
  415                         return (EINVAL);
  416                 switch (d) {
  417                     case VT_FALSE:
  418                     case VT_TRUE:
  419                         return (usl_detachack(sd, (d == VT_TRUE)));
  420                     case VT_ACKACQ:
  421                         return (usl_attachack(sd, 1));
  422                     default:
  423                         return (EINVAL);
  424                 }
  425 #undef d
  426                 return (0);
  427 
  428 #if defined(__i386__)
  429             case KDENABIO:
  430                 if (suser(p, 0) || securelevel > 0)
  431                         return (EPERM);
  432                 /* FALLTHROUGH */
  433             case KDDISABIO:
  434 #if defined(COMPAT_FREEBSD)
  435                 {
  436                 struct trapframe *fp = (struct trapframe *)p->p_md.md_regs;
  437                 extern struct emul emul_freebsd_aout;
  438                 extern struct emul emul_freebsd_elf;
  439 
  440                 if (p->p_emul == &emul_freebsd_aout ||
  441                     p->p_emul == &emul_freebsd_elf) {
  442                         if (cmd == KDENABIO)
  443                                 fp->tf_eflags |= PSL_IOPL;
  444                         else
  445                                 fp->tf_eflags &= ~PSL_IOPL;
  446                         }
  447                 }
  448 #endif
  449                 return (0);
  450 #else
  451             case KDENABIO:
  452             case KDDISABIO:
  453                 /*
  454                  * This is a lie, but non-x86 platforms are not supposed to
  455                  * issue these ioctls anyway.
  456                  */
  457                 return (0);
  458 #endif
  459             case KDSETRAD:
  460                 /* XXX ignore for now */
  461                 return (0);
  462 
  463             default:
  464                 return (-1);
  465 
  466             /*
  467              * the following are converted to wsdisplay ioctls
  468              */
  469             case KDSETMODE:
  470                 req = WSDISPLAYIO_SMODE;
  471 #define d (*(int *)data)
  472                 switch (d) {
  473                     case KD_GRAPHICS:
  474                         intarg = WSDISPLAYIO_MODE_MAPPED;
  475                         break;
  476                     case KD_TEXT:
  477                         intarg = WSDISPLAYIO_MODE_EMUL;
  478                         break;
  479                     default:
  480                         return (EINVAL);
  481                 }
  482 #undef d
  483                 arg = &intarg;
  484                 break;
  485             case KDMKTONE:
  486                 req = WSKBDIO_COMPLEXBELL;
  487 #define d (*(int *)data)
  488                 if (d) {
  489 #define PCVT_SYSBEEPF   1193182
  490                         if (d >> 16) {
  491                                 bd.which = WSKBD_BELL_DOPERIOD;
  492                         bd.period = d >> 16; /* ms */
  493                         }
  494                         else
  495                                 bd.which = 0;
  496                         if (d & 0xffff) {
  497                                 bd.which |= WSKBD_BELL_DOPITCH;
  498                                 bd.pitch = PCVT_SYSBEEPF/(d & 0xffff); /* Hz */
  499                         }
  500                 } else
  501                         bd.which = 0; /* default */
  502 #undef d
  503                 arg = &bd;
  504                 break;
  505             case KDSETLED:
  506                 req = WSKBDIO_SETLEDS;
  507                 intarg = 0;
  508 #define d (*(int *)data)
  509                 if (d & LED_CAP)
  510                         intarg |= WSKBD_LED_CAPS;
  511                 if (d & LED_NUM)
  512                         intarg |= WSKBD_LED_NUM;
  513                 if (d & LED_SCR)
  514                         intarg |= WSKBD_LED_SCROLL;
  515 #undef d
  516                 arg = &intarg;
  517                 break;
  518             case KDGETLED:
  519                 req = WSKBDIO_GETLEDS;
  520                 arg = &intarg;
  521                 break;
  522 #ifdef WSDISPLAY_COMPAT_RAWKBD
  523             case KDSKBMODE:
  524                 req = WSKBDIO_SETMODE;
  525                 switch (*(int *)data) {
  526                     case K_RAW:
  527                         intarg = WSKBD_RAW;
  528                         break;
  529                     case K_XLATE:
  530                         intarg = WSKBD_TRANSLATED;
  531                         break;
  532                     default:
  533                         return (EINVAL);
  534                 }
  535                 arg = &intarg;
  536                 break;
  537             case KDGKBMODE:
  538                 req = WSKBDIO_GETMODE;
  539                 arg = &intarg;
  540                 break;
  541 #endif
  542         }
  543 
  544         res = wsdisplay_internal_ioctl(sc, scr, req, arg, flag, p);
  545         if (res)
  546                 return (res);
  547 
  548         switch (cmd) {
  549             case KDGETLED:
  550 #define d (*(int *)data)
  551                 d = 0;
  552                 if (intarg & WSKBD_LED_CAPS)
  553                         d |= LED_CAP;
  554                 if (intarg & WSKBD_LED_NUM)
  555                         d |= LED_NUM;
  556                 if (intarg & WSKBD_LED_SCROLL)
  557                         d |= LED_SCR;
  558 #undef d
  559                 break;
  560 #ifdef WSDISPLAY_COMPAT_RAWKBD
  561             case KDGKBMODE:
  562                 *(int *)data = (intarg == WSKBD_RAW ? K_RAW : K_XLATE);
  563                 break;
  564 #endif
  565         }
  566 
  567         return (0);
  568 }

/* [<][>][^][v][top][bottom][index][help] */