[BACK]Return to wsdisplay_compat_usl.c CVS log [TXT][DIR] Up to [local] / sys / dev / wscons

Annotation of sys/dev/wscons/wsdisplay_compat_usl.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb