Annotation of embedaddon/ntp/libparse/parsesolaris.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * /src/NTP/ntp4-dev/libparse/parsesolaris.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A
        !             3:  *  
        !             4:  * parsesolaris.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A
        !             5:  *
        !             6:  * STREAMS module for reference clocks
        !             7:  *
        !             8:  * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
        !             9:  * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. Neither the name of the author nor the names of its contributors
        !            20:  *    may be used to endorse or promote products derived from this software
        !            21:  *    without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            33:  * SUCH DAMAGE.
        !            34:  *
        !            35:  */
        !            36: 
        !            37: #define _KERNEL                        /* it is a _KERNEL module */
        !            38: 
        !            39: #ifndef lint
        !            40: static char rcsid[] = "parsesolaris.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A";
        !            41: #endif
        !            42: 
        !            43: #include <sys/types.h>
        !            44: #include <sys/conf.h>
        !            45: #include <sys/errno.h>
        !            46: #include <sys/time.h>
        !            47: #include <sys/termios.h>
        !            48: #include <sys/stream.h>
        !            49: #include <sys/strtty.h>
        !            50: #include <sys/stropts.h>
        !            51: #include <sys/modctl.h>
        !            52: #include <sys/ddi.h>
        !            53: #include <sys/sunddi.h>
        !            54: #ifdef __GNUC__ /* makes it compile on Solaris 2.6 - acc doesn't like it -- GREAT! */
        !            55: #include <stdarg.h>
        !            56: #endif
        !            57: 
        !            58: #include "ntp_fp.h"
        !            59: #include "parse.h"
        !            60: #include <sys/parsestreams.h>
        !            61: 
        !            62: /*--------------- loadable driver section -----------------------------*/
        !            63: 
        !            64: static struct streamtab parseinfo;
        !            65: 
        !            66: static struct fmodsw fmod_templ =
        !            67: {
        !            68:        "parse",                        /* module name */
        !            69:        &parseinfo,                     /* module information */
        !            70:        D_NEW|D_MP|D_MTQPAIR,           /* exclusive for q pair */
        !            71:        /* lock ptr */
        !            72: };
        !            73: 
        !            74: extern struct mod_ops mod_strmodops;
        !            75: 
        !            76: static struct modlstrmod modlstrmod = 
        !            77: {
        !            78:        &mod_strmodops,         /* a STREAMS module */
        !            79:        "PARSE      - NTP reference",   /* name this baby - keep room for revision number */
        !            80:        &fmod_templ
        !            81: };
        !            82: 
        !            83: static struct modlinkage modlinkage =
        !            84: {
        !            85:        MODREV_1,
        !            86:        {
        !            87:                &modlstrmod,
        !            88:                NULL
        !            89:        }
        !            90: };
        !            91: 
        !            92: /*
        !            93:  * module management routines
        !            94:  */
        !            95: /*ARGSUSED*/
        !            96: int
        !            97: _init(
        !            98:      void
        !            99:      )
        !           100: {
        !           101:        static char revision[] = "4.6";
        !           102:        char *s, *S; 
        !           103:        char *t;
        !           104:   
        !           105: #ifndef lint
        !           106:        t = rcsid;
        !           107: #endif
        !           108:        
        !           109:        /*
        !           110:         * copy RCS revision into Drv_name
        !           111:         *
        !           112:         * are we forcing RCS here to do things it was not built for ?
        !           113:         */
        !           114:        s = revision;
        !           115:        if (*s == '$')
        !           116:        {
        !           117:                /*
        !           118:                 * skip "$Revision: "
        !           119:                 * if present. - not necessary on a -kv co (cvs export)
        !           120:                 */
        !           121:                while (*s && (*s != ' '))
        !           122:                {
        !           123:                        s++;
        !           124:                }
        !           125:                if (*s == ' ') s++;
        !           126:        }
        !           127:          
        !           128:        t = modlstrmod.strmod_linkinfo; 
        !           129:        while (*t && (*t != ' '))
        !           130:        {
        !           131:                t++;
        !           132:        }
        !           133:        if (*t == ' ') t++;
        !           134:          
        !           135:        S = s;
        !           136:        while (*S && (((*S >= '0') && (*S <= '9')) || (*S == '.')))
        !           137:        {
        !           138:                S++;
        !           139:        }
        !           140:          
        !           141:        if (*s && *t && (S > s))
        !           142:        {
        !           143:                if (strlen(t) >= (S - s))
        !           144:                {
        !           145:                        (void) strncpy(t, s, (unsigned)(S - s));
        !           146:                }
        !           147:        }
        !           148:        return (mod_install(&modlinkage));
        !           149: }
        !           150: 
        !           151: /*ARGSUSED*/
        !           152: int
        !           153: _info(
        !           154:       struct modinfo *modinfop
        !           155:       )
        !           156: {
        !           157:        return (mod_info(&modlinkage, modinfop));
        !           158: }
        !           159: 
        !           160: /*ARGSUSED*/
        !           161: int
        !           162: _fini(
        !           163:       void
        !           164:       )
        !           165: {
        !           166:        if (mod_remove(&modlinkage) != DDI_SUCCESS)
        !           167:        {
        !           168:                return EBUSY;
        !           169:        }
        !           170:        else
        !           171:            return DDI_SUCCESS;
        !           172: }
        !           173: 
        !           174: /*--------------- stream module definition ----------------------------*/
        !           175: 
        !           176: static int parseopen  (queue_t *, dev_t *, int, int, cred_t *);
        !           177: static int parseclose (queue_t *, int);
        !           178: static int parsewput  (queue_t *, mblk_t *);
        !           179: static int parserput  (queue_t *, mblk_t *);
        !           180: static int parsersvc  (queue_t *);
        !           181: 
        !           182: static struct module_info driverinfo =
        !           183: {
        !           184:        0,                              /* module ID number */
        !           185:        fmod_templ.f_name,              /* module name - why repeated here ? compat ?*/
        !           186:        0,                              /* minimum accepted packet size */
        !           187:        INFPSZ,                         /* maximum accepted packet size */
        !           188:        1,                              /* high water mark - flow control */
        !           189:        0                               /* low water mark - flow control */
        !           190: };
        !           191: 
        !           192: static struct qinit rinit =    /* read queue definition */
        !           193: {
        !           194:        parserput,                      /* put procedure */
        !           195:        parsersvc,                      /* service procedure */
        !           196:        parseopen,                      /* open procedure */
        !           197:        parseclose,                     /* close procedure */
        !           198:        NULL,                           /* admin procedure - NOT USED FOR NOW */
        !           199:        &driverinfo,                    /* information structure */
        !           200:        NULL                            /* statistics */
        !           201: };
        !           202: 
        !           203: static struct qinit winit =    /* write queue definition */
        !           204: {
        !           205:        parsewput,                      /* put procedure */
        !           206:        NULL,                           /* service procedure */
        !           207:        NULL,                           /* open procedure */
        !           208:        NULL,                           /* close procedure */
        !           209:        NULL,                           /* admin procedure - NOT USED FOR NOW */
        !           210:        &driverinfo,                    /* information structure */
        !           211:        NULL                            /* statistics */
        !           212: };
        !           213: 
        !           214: static struct streamtab parseinfo =    /* stream info element for parse driver */
        !           215: {
        !           216:        &rinit,                 /* read queue */
        !           217:        &winit,                 /* write queue */
        !           218:        NULL,                           /* read mux */
        !           219:        NULL                            /* write mux */
        !           220: };
        !           221: 
        !           222: /*--------------- driver data structures ----------------------------*/
        !           223: 
        !           224: /*
        !           225:  * we usually have an inverted signal - but you
        !           226:  * can change this to suit your needs
        !           227:  */
        !           228: int cd_invert = 1;             /* invert status of CD line - PPS support via CD input */
        !           229: 
        !           230: #ifdef PARSEDEBUG
        !           231: int parsedebug = ~0;
        !           232: #else
        !           233: int parsedebug = 0;
        !           234: #endif
        !           235: 
        !           236: /*--------------- module implementation -----------------------------*/
        !           237: 
        !           238: #define TIMEVAL_USADD(_X_, _US_) do {\
        !           239:        (_X_)->tv_usec += (_US_);\
        !           240:        if ((_X_)->tv_usec >= 1000000)\
        !           241:        {\
        !           242:            (_X_)->tv_sec++;\
        !           243:            (_X_)->tv_usec -= 1000000;\
        !           244:        }\
        !           245:      } while (0)
        !           246: 
        !           247: static int init_linemon (queue_t *);
        !           248: static void close_linemon (queue_t *, queue_t *);
        !           249: 
        !           250: #define M_PARSE                0x0001
        !           251: #define M_NOPARSE      0x0002
        !           252: 
        !           253: void
        !           254: ntp_memset(
        !           255:        char *a,
        !           256:        int x,
        !           257:        int c
        !           258:        )
        !           259: {
        !           260:        while (c-- > 0)
        !           261:            *a++ = x;
        !           262: }
        !           263: 
        !           264: static void
        !           265: pprintf(
        !           266:        int lev,
        !           267:        char *form,
        !           268:        ...
        !           269:        )
        !           270: {
        !           271:        va_list ap;
        !           272: 
        !           273:        va_start(ap, form);
        !           274: 
        !           275:        if (lev & parsedebug)
        !           276:                vcmn_err(CE_CONT, form, ap);
        !           277: 
        !           278:        va_end(ap);
        !           279: }
        !           280: 
        !           281: static int
        !           282: setup_stream(
        !           283:             queue_t *q,
        !           284:             int mode
        !           285:             )
        !           286: {
        !           287:        register mblk_t *mp;
        !           288: 
        !           289:        pprintf(DD_OPEN,"parse: SETUP_STREAM - setting up stream for q=%x\n", q);
        !           290: 
        !           291:        mp = allocb(sizeof(struct stroptions), BPRI_MED);
        !           292:        if (mp)
        !           293:        {
        !           294:                struct stroptions *str = (struct stroptions *)mp->b_wptr;
        !           295: 
        !           296:                str->so_flags   = SO_READOPT|SO_HIWAT|SO_LOWAT|SO_ISNTTY;
        !           297:                str->so_readopt = (mode == M_PARSE) ? RMSGD : RNORM;
        !           298:                str->so_hiwat   = (mode == M_PARSE) ? sizeof(parsetime_t) : 256;
        !           299:                str->so_lowat   = 0;
        !           300:                mp->b_datap->db_type = M_SETOPTS;
        !           301:                mp->b_wptr     += sizeof(struct stroptions);
        !           302:                if (!q)
        !           303:                    panic("NULL q - strange");
        !           304:                putnext(q, mp);
        !           305:                return putctl1(WR(q)->q_next, M_CTL, (mode == M_PARSE) ? MC_SERVICEIMM :
        !           306:                               MC_SERVICEDEF);
        !           307:        }
        !           308:        else
        !           309:        {
        !           310:                pprintf(DD_OPEN, "parse: setup_stream - FAILED - no MEMORY for allocb\n"); 
        !           311:                return 0;
        !           312:        }
        !           313: }
        !           314: 
        !           315: /*ARGSUSED*/
        !           316: static int
        !           317: parseopen(
        !           318:          queue_t *q,
        !           319:          dev_t *dev,
        !           320:          int flag,
        !           321:          int sflag,
        !           322:          cred_t *credp
        !           323:          )
        !           324: {
        !           325:        register parsestream_t *parse;
        !           326:        static int notice = 0;
        !           327:   
        !           328:        pprintf(DD_OPEN, "parse: OPEN - q=%x\n", q); 
        !           329:   
        !           330:        if (sflag != MODOPEN)
        !           331:        {                       /* open only for modules */
        !           332:                pprintf(DD_OPEN, "parse: OPEN - FAILED - not MODOPEN\n"); 
        !           333:                return EIO;
        !           334:        }
        !           335: 
        !           336:        if (q->q_ptr != (caddr_t)NULL)
        !           337:        {
        !           338:                pprintf(DD_OPEN, "parse: OPEN - FAILED - EXCLUSIVE ONLY\n"); 
        !           339:                return EBUSY;
        !           340:        }
        !           341: 
        !           342:        q->q_ptr = (caddr_t)kmem_alloc(sizeof(parsestream_t), KM_SLEEP);
        !           343:        if (q->q_ptr == (caddr_t)0)
        !           344:        {
        !           345:                return ENOMEM;
        !           346:        }
        !           347: 
        !           348:        pprintf(DD_OPEN, "parse: OPEN - parse area q=%x, q->q_ptr=%x\n", q, q->q_ptr); 
        !           349:        WR(q)->q_ptr = q->q_ptr;
        !           350:        pprintf(DD_OPEN, "parse: OPEN - WQ parse area q=%x, q->q_ptr=%x\n", WR(q), WR(q)->q_ptr); 
        !           351:   
        !           352:        parse = (parsestream_t *) q->q_ptr;
        !           353:        bzero((caddr_t)parse, sizeof(*parse));
        !           354:        parse->parse_queue     = q;
        !           355:        parse->parse_status    = PARSE_ENABLE;
        !           356:        parse->parse_ppsclockev.tv.tv_sec  = 0;
        !           357:        parse->parse_ppsclockev.tv.tv_usec = 0;
        !           358:        parse->parse_ppsclockev.serial     = 0;
        !           359: 
        !           360:        qprocson(q);
        !           361: 
        !           362:        pprintf(DD_OPEN, "parse: OPEN - initializing io subsystem q=%x\n", q); 
        !           363: 
        !           364:        if (!parse_ioinit(&parse->parse_io))
        !           365:        {
        !           366:                /*
        !           367:                 * ok guys - beat it
        !           368:                 */
        !           369:                qprocsoff(q);
        !           370: 
        !           371:                kmem_free((caddr_t)parse, sizeof(parsestream_t));
        !           372: 
        !           373:                return EIO;
        !           374:        }
        !           375: 
        !           376:        pprintf(DD_OPEN, "parse: OPEN - initializing stream q=%x\n", q); 
        !           377: 
        !           378:        if (setup_stream(q, M_PARSE))
        !           379:        {
        !           380:                (void) init_linemon(q); /* hook up PPS ISR routines if possible */
        !           381:                pprintf(DD_OPEN, "parse: OPEN - SUCCEEDED\n"); 
        !           382: 
        !           383:                /*
        !           384:                 * I know that you know the delete key, but you didn't write this
        !           385:                 * code, did you ? - So, keep the message in here.
        !           386:                 */
        !           387:                if (!notice)
        !           388:                {
        !           389:                  cmn_err(CE_CONT, "?%s: Copyright (c) 1993-2005, Frank Kardel\n", modlstrmod.strmod_linkinfo);
        !           390:                        notice = 1;
        !           391:                }
        !           392: 
        !           393:                return 0;
        !           394:        }
        !           395:        else
        !           396:        {
        !           397:                qprocsoff(q);
        !           398: 
        !           399:                kmem_free((caddr_t)parse, sizeof(parsestream_t));
        !           400: 
        !           401:                return EIO;
        !           402:        }
        !           403: }
        !           404: 
        !           405: /*ARGSUSED*/
        !           406: static int
        !           407: parseclose(
        !           408:           queue_t *q,
        !           409:           int flags
        !           410:           )
        !           411: {
        !           412:        register parsestream_t *parse = (parsestream_t *)q->q_ptr;
        !           413:        register unsigned long s;
        !           414:   
        !           415:        pprintf(DD_CLOSE, "parse: CLOSE\n");
        !           416:   
        !           417:        qprocsoff(q);
        !           418: 
        !           419:        s = splhigh();
        !           420:   
        !           421:        if (parse->parse_dqueue)
        !           422:            close_linemon(parse->parse_dqueue, q);
        !           423:        parse->parse_dqueue = (queue_t *)0;
        !           424: 
        !           425:        (void) splx(s);
        !           426:       
        !           427:        parse_ioend(&parse->parse_io);
        !           428: 
        !           429:        kmem_free((caddr_t)parse, sizeof(parsestream_t));
        !           430: 
        !           431:        q->q_ptr = (caddr_t)NULL;
        !           432:        WR(q)->q_ptr = (caddr_t)NULL;
        !           433: 
        !           434:        return 0;
        !           435: }
        !           436: 
        !           437: /*
        !           438:  * move unrecognized stuff upward
        !           439:  */
        !           440: static int
        !           441: parsersvc(
        !           442:          queue_t *q
        !           443:          )
        !           444: {
        !           445:        mblk_t *mp;
        !           446:   
        !           447:        while ((mp = getq(q)))
        !           448:        {
        !           449:                if (canputnext(q) || (mp->b_datap->db_type > QPCTL))
        !           450:                {
        !           451:                        putnext(q, mp);
        !           452:                        pprintf(DD_RSVC, "parse: RSVC - putnext\n");
        !           453:                }
        !           454:                else
        !           455:                {
        !           456:                        putbq(q, mp);
        !           457:                        pprintf(DD_RSVC, "parse: RSVC - flow control wait\n");
        !           458:                        break;
        !           459:                }
        !           460:        }
        !           461:        return 0;
        !           462: }
        !           463: 
        !           464: /*
        !           465:  * do ioctls and
        !           466:  * send stuff down - dont care about
        !           467:  * flow control
        !           468:  */
        !           469: static int
        !           470: parsewput(
        !           471:          queue_t *q,
        !           472:          mblk_t *mp
        !           473:          )
        !           474: {
        !           475:        register int ok = 1;
        !           476:        register mblk_t *datap;
        !           477:        register struct iocblk *iocp;
        !           478:        parsestream_t         *parse = (parsestream_t *)q->q_ptr;
        !           479:   
        !           480:        pprintf(DD_WPUT, "parse: parsewput\n");
        !           481:   
        !           482:        switch (mp->b_datap->db_type)
        !           483:        {
        !           484:            default:
        !           485:                putnext(q, mp);
        !           486:                break;
        !           487:       
        !           488:            case M_IOCTL:
        !           489:                iocp = (struct iocblk *)mp->b_rptr;
        !           490:                switch (iocp->ioc_cmd)
        !           491:                {
        !           492:                    default:
        !           493:                        pprintf(DD_WPUT, "parse: parsewput - forward M_IOCTL\n");
        !           494:                        putnext(q, mp);
        !           495:                        break;
        !           496: 
        !           497:                    case CIOGETEV:
        !           498:                        /*
        !           499:                         * taken from Craig Leres ppsclock module (and modified)
        !           500:                         */
        !           501:                        datap = allocb(sizeof(struct ppsclockev), BPRI_MED);
        !           502:                        if (datap == NULL || mp->b_cont)
        !           503:                        {
        !           504:                                mp->b_datap->db_type = M_IOCNAK;
        !           505:                                iocp->ioc_error = (datap == NULL) ? ENOMEM : EINVAL;
        !           506:                                if (datap != NULL)
        !           507:                                    freeb(datap);
        !           508:                                qreply(q, mp);
        !           509:                                break;
        !           510:                        }
        !           511: 
        !           512:                        mp->b_cont = datap;
        !           513:                        *(struct ppsclockev *)datap->b_wptr = parse->parse_ppsclockev;
        !           514:                        datap->b_wptr +=
        !           515:                                sizeof(struct ppsclockev) / sizeof(*datap->b_wptr);
        !           516:                        mp->b_datap->db_type = M_IOCACK;
        !           517:                        iocp->ioc_count = sizeof(struct ppsclockev);
        !           518:                        qreply(q, mp);
        !           519:                        break;
        !           520:          
        !           521:                    case PARSEIOC_ENABLE:
        !           522:                    case PARSEIOC_DISABLE:
        !           523:                            {
        !           524:                                    parse->parse_status = (parse->parse_status & (unsigned)~PARSE_ENABLE) |
        !           525:                                            (iocp->ioc_cmd == PARSEIOC_ENABLE) ?
        !           526:                                            PARSE_ENABLE : 0;
        !           527:                                    if (!setup_stream(RD(q), (parse->parse_status & PARSE_ENABLE) ?
        !           528:                                                      M_PARSE : M_NOPARSE))
        !           529:                                    {
        !           530:                                            mp->b_datap->db_type = M_IOCNAK;
        !           531:                                    }
        !           532:                                    else
        !           533:                                    {
        !           534:                                            mp->b_datap->db_type = M_IOCACK;
        !           535:                                    }
        !           536:                                    qreply(q, mp);
        !           537:                                    break;
        !           538:                            }       
        !           539: 
        !           540:                    case PARSEIOC_TIMECODE:
        !           541:                    case PARSEIOC_SETFMT:
        !           542:                    case PARSEIOC_GETFMT:
        !           543:                    case PARSEIOC_SETCS:
        !           544:                        if (iocp->ioc_count == sizeof(parsectl_t))
        !           545:                        {
        !           546:                                parsectl_t *dct = (parsectl_t *)mp->b_cont->b_rptr;
        !           547: 
        !           548:                                switch (iocp->ioc_cmd)
        !           549:                                {
        !           550:                                    case PARSEIOC_TIMECODE:
        !           551:                                        pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_TIMECODE\n");
        !           552:                                        ok = parse_timecode(dct, &parse->parse_io);
        !           553:                                        break;
        !           554:                  
        !           555:                                    case PARSEIOC_SETFMT:
        !           556:                                        pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_SETFMT\n");
        !           557:                                        ok = parse_setfmt(dct, &parse->parse_io);
        !           558:                                        break;
        !           559: 
        !           560:                                    case PARSEIOC_GETFMT:
        !           561:                                        pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_GETFMT\n");
        !           562:                                        ok = parse_getfmt(dct, &parse->parse_io);
        !           563:                                        break;
        !           564: 
        !           565:                                    case PARSEIOC_SETCS:
        !           566:                                        pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_SETCS\n");
        !           567:                                        ok = parse_setcs(dct, &parse->parse_io);
        !           568:                                        break;
        !           569:                                }
        !           570:                                mp->b_datap->db_type = ok ? M_IOCACK : M_IOCNAK;
        !           571:                        }
        !           572:                        else
        !           573:                        {
        !           574:                                mp->b_datap->db_type = M_IOCNAK;
        !           575:                        }
        !           576:                        pprintf(DD_WPUT, "parse: parsewput qreply - %s\n", (mp->b_datap->db_type == M_IOCNAK) ? "M_IOCNAK" : "M_IOCACK");
        !           577:                        qreply(q, mp);
        !           578:                        break;
        !           579:                }
        !           580:        }
        !           581:        return 0;
        !           582: }
        !           583: 
        !           584: /*
        !           585:  * read characters from streams buffers
        !           586:  */
        !           587: static unsigned long
        !           588: rdchar(
        !           589:        mblk_t **mp
        !           590:        )
        !           591: {
        !           592:        while (*mp != (mblk_t *)NULL)
        !           593:        {
        !           594:                if ((*mp)->b_wptr - (*mp)->b_rptr)
        !           595:                {
        !           596:                        return (unsigned long)(*(unsigned char *)((*mp)->b_rptr++));
        !           597:                }
        !           598:                else
        !           599:                {
        !           600:                        register mblk_t *mmp = *mp;
        !           601:          
        !           602:                        *mp = (*mp)->b_cont;
        !           603:                        freeb(mmp);
        !           604:                }
        !           605:        }
        !           606:        return (unsigned long)~0;
        !           607: }
        !           608: 
        !           609: /*
        !           610:  * convert incoming data
        !           611:  */
        !           612: static int
        !           613: parserput(
        !           614:          queue_t *q,
        !           615:          mblk_t *imp
        !           616:          )
        !           617: {
        !           618:        register unsigned char type;
        !           619:        mblk_t *mp = imp;
        !           620:   
        !           621:        switch (type = mp->b_datap->db_type)
        !           622:        {
        !           623:            default:
        !           624:                /*
        !           625:                 * anything we don't know will be put on queue
        !           626:                 * the service routine will move it to the next one
        !           627:                 */
        !           628:                pprintf(DD_RPUT, "parse: parserput - forward type 0x%x\n", type);
        !           629: 
        !           630:                if (canputnext(q) || (mp->b_datap->db_type > QPCTL))
        !           631:                {
        !           632:                        putnext(q, mp);
        !           633:                }
        !           634:                else
        !           635:                    putq(q, mp);
        !           636:                break;
        !           637:       
        !           638:            case M_BREAK:
        !           639:            case M_DATA:
        !           640:                    {
        !           641:                            register parsestream_t * parse = (parsestream_t *)q->q_ptr;
        !           642:                            register mblk_t *nmp;
        !           643:                            register unsigned long ch;
        !           644:                            timestamp_t c_time;
        !           645:                            timespec_t hres_time;
        !           646: 
        !           647:                            /*
        !           648:                             * get time on packet delivery
        !           649:                             */
        !           650:                            gethrestime(&hres_time);
        !           651:                            c_time.tv.tv_sec  = hres_time.tv_sec;
        !           652:                            c_time.tv.tv_usec = hres_time.tv_nsec / 1000;
        !           653: 
        !           654:                            if (!(parse->parse_status & PARSE_ENABLE))
        !           655:                            {
        !           656:                                    pprintf(DD_RPUT, "parse: parserput - parser disabled - forward type 0x%x\n", type);
        !           657:                                    if (canputnext(q) || (mp->b_datap->db_type > QPCTL))
        !           658:                                    {
        !           659:                                            putnext(q, mp);
        !           660:                                    }
        !           661:                                    else
        !           662:                                        putq(q, mp);
        !           663:                            }
        !           664:                            else
        !           665:                            {
        !           666:                                    pprintf(DD_RPUT, "parse: parserput - M_%s\n", (type == M_DATA) ? "DATA" : "BREAK");
        !           667:                                    if (type == M_DATA)
        !           668:                                    {
        !           669:                                            /*
        !           670:                                             * parse packet looking for start an end characters
        !           671:                                             */
        !           672:                                            while (mp != (mblk_t *)NULL)
        !           673:                                            {
        !           674:                                                    ch = rdchar(&mp);
        !           675:                                                    if (ch != ~0 && parse_ioread(&parse->parse_io, (unsigned int)ch, &c_time))
        !           676:                                                    {
        !           677:                                                            /*
        !           678:                                                             * up up and away (hopefully ...)
        !           679:                                                             * don't press it if resources are tight or nobody wants it
        !           680:                                                             */
        !           681:                                                            nmp = (mblk_t *)NULL;
        !           682:                                                            if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED)))
        !           683:                                                            {
        !           684:                                                                    bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t));
        !           685:                                                                    nmp->b_wptr += sizeof(parsetime_t);
        !           686:                                                                    putnext(parse->parse_queue, nmp);
        !           687:                                                            }
        !           688:                                                            else
        !           689:                                                                if (nmp) freemsg(nmp);
        !           690:                                                            parse_iodone(&parse->parse_io);
        !           691:                                                    }
        !           692:                                            }   
        !           693:                                    }
        !           694:                                    else
        !           695:                                    {
        !           696:                                            if (parse_ioread(&parse->parse_io, (unsigned int)0, &c_time))
        !           697:                                            {
        !           698:                                                    /*
        !           699:                                                     * up up and away (hopefully ...)
        !           700:                                                     * don't press it if resources are tight or nobody wants it
        !           701:                                                     */
        !           702:                                                    nmp = (mblk_t *)NULL;
        !           703:                                                    if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED)))
        !           704:                                                    {
        !           705:                                                            bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t));
        !           706:                                                            nmp->b_wptr += sizeof(parsetime_t);
        !           707:                                                            putnext(parse->parse_queue, nmp);
        !           708:                                                    }
        !           709:                                                    else
        !           710:                                                        if (nmp) freemsg(nmp);
        !           711:                                                    parse_iodone(&parse->parse_io);
        !           712:                                            }
        !           713:                                            freemsg(mp);
        !           714:                                    }
        !           715:                                    break;
        !           716:                            }
        !           717:                    }
        !           718: 
        !           719:                    /*
        !           720:                     * CD PPS support for non direct ISR hack
        !           721:                     */
        !           722:            case M_HANGUP:
        !           723:            case M_UNHANGUP:
        !           724:                    {
        !           725:                            register parsestream_t * parse = (parsestream_t *)q->q_ptr;
        !           726:                            timestamp_t c_time;
        !           727:                            timespec_t hres_time;
        !           728:                            register mblk_t *nmp;
        !           729:                            register int status = cd_invert ^ (type == M_UNHANGUP);
        !           730: 
        !           731:                            gethrestime(&hres_time);
        !           732:                            c_time.tv.tv_sec  = hres_time.tv_sec;
        !           733:                            c_time.tv.tv_usec = hres_time.tv_nsec / 1000;
        !           734:        
        !           735:                            pprintf(DD_RPUT, "parse: parserput - M_%sHANGUP\n", (type == M_HANGUP) ? "" : "UN");
        !           736: 
        !           737:                            if ((parse->parse_status & PARSE_ENABLE) &&
        !           738:                                parse_iopps(&parse->parse_io, status ? SYNC_ONE : SYNC_ZERO, &c_time))
        !           739:                            {
        !           740:                                    nmp = (mblk_t *)NULL;
        !           741:                                    if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED)))
        !           742:                                    {
        !           743:                                            bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t));
        !           744:                                            nmp->b_wptr += sizeof(parsetime_t);
        !           745:                                            putnext(parse->parse_queue, nmp);
        !           746:                                    }
        !           747:                                    else
        !           748:                                        if (nmp) freemsg(nmp);
        !           749:                                    parse_iodone(&parse->parse_io);
        !           750:                                    freemsg(mp);
        !           751:                            }
        !           752:                            else
        !           753:                                if (canputnext(q) || (mp->b_datap->db_type > QPCTL))
        !           754:                                {
        !           755:                                        putnext(q, mp);
        !           756:                                }
        !           757:                                else
        !           758:                                    putq(q, mp);
        !           759:        
        !           760:                            if (status)
        !           761:                            {
        !           762:                                    parse->parse_ppsclockev.tv = c_time.tv;
        !           763:                                    ++(parse->parse_ppsclockev.serial);
        !           764:                            }
        !           765:                    }
        !           766:        }
        !           767:        return 0;
        !           768: }
        !           769: 
        !           770: static int  init_zs_linemon  (queue_t *, queue_t *);   /* handle line monitor for "zs" driver */
        !           771: static void close_zs_linemon (queue_t *, queue_t *);
        !           772: 
        !           773: /*-------------------- CD isr status monitor ---------------*/
        !           774: 
        !           775: static int
        !           776: init_linemon(
        !           777:             queue_t *q
        !           778:             )
        !           779: {
        !           780:        register queue_t *dq;
        !           781:   
        !           782:        dq = WR(q);
        !           783:        /*
        !           784:         * we ARE doing very bad things down here (basically stealing ISR
        !           785:         * hooks)
        !           786:         *
        !           787:         * so we chase down the STREAMS stack searching for the driver
        !           788:         * and if this is a known driver we insert our ISR routine for
        !           789:         * status changes in to the ExternalStatus handling hook
        !           790:         */
        !           791:        while (dq->q_next)
        !           792:        {
        !           793:                dq = dq->q_next;                /* skip down to driver */
        !           794:        }
        !           795: 
        !           796:        /*
        !           797:         * find appropriate driver dependent routine
        !           798:         */
        !           799:        if (dq->q_qinfo && dq->q_qinfo->qi_minfo)
        !           800:        {
        !           801:                register char *dname = dq->q_qinfo->qi_minfo->mi_idname;
        !           802: 
        !           803:                pprintf(DD_INSTALL, "init_linemon: driver is \"%s\"\n", dname);
        !           804: 
        !           805: #ifdef sun
        !           806:                if (dname && !strcmp(dname, "zs"))
        !           807:                {
        !           808:                        return init_zs_linemon(dq, q);
        !           809:                }
        !           810:                else
        !           811: #endif
        !           812:                {
        !           813:                        pprintf(DD_INSTALL, "init_linemon: driver \"%s\" not suitable for CD monitoring\n", dname);
        !           814:                        return 0;
        !           815:                }
        !           816:        }
        !           817:        pprintf(DD_INSTALL, "init_linemon: cannot find driver\n");
        !           818:        return 0;
        !           819: }
        !           820: 
        !           821: static void
        !           822: close_linemon(
        !           823:              queue_t *q,
        !           824:              queue_t *my_q
        !           825:              )
        !           826: {
        !           827:        /*
        !           828:         * find appropriate driver dependent routine
        !           829:         */
        !           830:        if (q->q_qinfo && q->q_qinfo->qi_minfo)
        !           831:        {
        !           832:                register char *dname = q->q_qinfo->qi_minfo->mi_idname;
        !           833: 
        !           834: #ifdef sun
        !           835:                if (dname && !strcmp(dname, "zs"))
        !           836:                {
        !           837:                        close_zs_linemon(q, my_q);
        !           838:                        return;
        !           839:                }
        !           840:                pprintf(DD_INSTALL, "close_linemon: cannot find driver close routine for \"%s\"\n", dname);
        !           841: #endif
        !           842:        }
        !           843:        pprintf(DD_INSTALL, "close_linemon: cannot find driver name\n");
        !           844: }
        !           845: 
        !           846: #ifdef sun
        !           847: #include <sys/tty.h>
        !           848: #include <sys/zsdev.h>
        !           849: #include <sys/ser_async.h>
        !           850: #include <sys/ser_zscc.h>
        !           851: 
        !           852: static void zs_xsisr         (struct zscom *); /* zs external status interupt handler */
        !           853: 
        !           854: /*
        !           855:  * there should be some docs telling how to get to
        !           856:  * sz:zs_usec_delay and zs:initzsops()
        !           857:  */
        !           858: #define zs_usec_delay 5
        !           859: 
        !           860: struct savedzsops
        !           861: {
        !           862:        struct zsops  zsops;
        !           863:        struct zsops *oldzsops;
        !           864: };
        !           865: 
        !           866: static struct zsops   *emergencyzs;
        !           867: 
        !           868: static int
        !           869: init_zs_linemon(
        !           870:                queue_t *q,
        !           871:                queue_t *my_q
        !           872:                )
        !           873: {
        !           874:        register struct zscom *zs;
        !           875:        register struct savedzsops *szs;
        !           876:        register parsestream_t  *parsestream = (parsestream_t *)my_q->q_ptr;
        !           877:        /*
        !           878:         * we expect the zsaline pointer in the q_data pointer
        !           879:         * from there on we insert our on EXTERNAL/STATUS ISR routine
        !           880:         * into the interrupt path, before the standard handler
        !           881:         */
        !           882:        zs = ((struct asyncline *)q->q_ptr)->za_common;
        !           883:        if (!zs)
        !           884:        {
        !           885:                /*
        !           886:                 * well - not found on startup - just say no (shouldn't happen though)
        !           887:                 */
        !           888:                return 0;
        !           889:        }
        !           890:        else
        !           891:        {
        !           892:                /*
        !           893:                 * we do a direct replacement, in case others fiddle also
        !           894:                 * if somebody else grabs our hook and we disconnect
        !           895:                 * we are in DEEP trouble - panic is likely to be next, sorry
        !           896:                 */
        !           897:                szs = (struct savedzsops *) kmem_alloc(sizeof(struct savedzsops), KM_SLEEP);
        !           898: 
        !           899:                if (szs == (struct savedzsops *)0)
        !           900:                {
        !           901:                        pprintf(DD_INSTALL, "init_zs_linemon: CD monitor NOT installed - no memory\n");
        !           902: 
        !           903:                        return 0;
        !           904:                }
        !           905:                else
        !           906:                {
        !           907:                        parsestream->parse_data   = (void *)szs;
        !           908: 
        !           909:                        mutex_enter(zs->zs_excl);
        !           910: 
        !           911:                        parsestream->parse_dqueue = q; /* remember driver */
        !           912: 
        !           913:                        szs->zsops            = *zs->zs_ops;
        !           914:                        szs->zsops.zsop_xsint = (void (*) (struct zscom *))zs_xsisr; /* place our bastard */
        !           915:                        szs->oldzsops         = zs->zs_ops;
        !           916:                        emergencyzs           = zs->zs_ops;
        !           917:          
        !           918:                        zs->zs_ops = &szs->zsops; /* hook it up */
        !           919:                        /*
        !           920:                         * XXX: this is usually done via zsopinit() 
        !           921:                         * - have yet to find a way to call that routine
        !           922:                         */
        !           923:                        zs->zs_xsint          = (void (*) (struct zscom *))zs_xsisr;
        !           924:          
        !           925:                        mutex_exit(zs->zs_excl);
        !           926: 
        !           927:                        pprintf(DD_INSTALL, "init_zs_linemon: CD monitor installed\n");
        !           928: 
        !           929:                        return 1;
        !           930:                }
        !           931:        }
        !           932: }
        !           933: 
        !           934: /*
        !           935:  * unregister our ISR routine - must call under splhigh() (or 
        !           936:  * whatever block ZS status interrupts)
        !           937:  */
        !           938: static void
        !           939: close_zs_linemon(
        !           940:                 queue_t *q,
        !           941:                 queue_t *my_q
        !           942:                 )
        !           943: {
        !           944:        register struct zscom *zs;
        !           945:        register parsestream_t  *parsestream = (parsestream_t *)my_q->q_ptr;
        !           946: 
        !           947:        zs = ((struct asyncline *)q->q_ptr)->za_common;
        !           948:        if (!zs)
        !           949:        {
        !           950:                /*
        !           951:                 * well - not found on startup - just say no (shouldn't happen though)
        !           952:                 */
        !           953:                return;
        !           954:        }
        !           955:        else
        !           956:        {
        !           957:                register struct savedzsops *szs = (struct savedzsops *)parsestream->parse_data;
        !           958: 
        !           959:                mutex_enter(zs->zs_excl);
        !           960: 
        !           961:                zs->zs_ops = szs->oldzsops; /* reset to previous handler functions */
        !           962:                /*
        !           963:                 * XXX: revert xsint (usually done via zsopinit() - have still to find
        !           964:                 * a way to call that bugger
        !           965:                 */
        !           966:                zs->zs_xsint = zs->zs_ops->zsop_xsint;
        !           967: 
        !           968:                mutex_exit(zs->zs_excl);
        !           969: 
        !           970:                kmem_free((caddr_t)szs, sizeof (struct savedzsops));
        !           971:       
        !           972:                pprintf(DD_INSTALL, "close_zs_linemon: CD monitor deleted\n");
        !           973:                return;
        !           974:        }
        !           975: }
        !           976: 
        !           977: #define ZSRR0_IGNORE   (ZSRR0_CD|ZSRR0_SYNC|ZSRR0_CTS)
        !           978: 
        !           979: #define MAXDEPTH 50            /* maximum allowed stream crawl */
        !           980: 
        !           981: /*
        !           982:  * take external status interrupt (only CD interests us)
        !           983:  */
        !           984: static void
        !           985: zs_xsisr(
        !           986:         struct zscom *zs
        !           987:         )
        !           988: {
        !           989:        register struct asyncline *za = (struct asyncline *)zs->zs_priv;
        !           990:        register queue_t *q;
        !           991:        register unsigned char zsstatus;
        !           992:        register int loopcheck;
        !           993:        register unsigned char cdstate;
        !           994:        register const char *dname = "-UNKNOWN-";
        !           995:        timespec_t hres_time;
        !           996: 
        !           997:        /*
        !           998:         * pick up current state
        !           999:         */
        !          1000:        zsstatus = SCC_READ0();
        !          1001: 
        !          1002:        if (za->za_rr0 ^ (cdstate = zsstatus & ZSRR0_CD))
        !          1003:        {
        !          1004:                timestamp_t cdevent;
        !          1005:                register int status;
        !          1006:       
        !          1007:                /*
        !          1008:                 * time stamp
        !          1009:                 */
        !          1010:                gethrestime(&hres_time);
        !          1011:                cdevent.tv.tv_sec  = hres_time.tv_sec;
        !          1012:                cdevent.tv.tv_usec = hres_time.tv_nsec / 1000;
        !          1013: 
        !          1014:                q = za->za_ttycommon.t_readq;
        !          1015: 
        !          1016:                /*
        !          1017:                 * logical state
        !          1018:                 */
        !          1019:                status = cd_invert ? cdstate == 0 : cdstate != 0;
        !          1020: 
        !          1021:                /*
        !          1022:                 * ok - now the hard part - find ourself
        !          1023:                 */
        !          1024:                loopcheck = MAXDEPTH;
        !          1025:       
        !          1026:                while (q)
        !          1027:                {
        !          1028:                        if (q->q_qinfo && q->q_qinfo->qi_minfo)
        !          1029:                        {
        !          1030:                                dname = q->q_qinfo->qi_minfo->mi_idname;
        !          1031: 
        !          1032:                                if (!strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname))
        !          1033:                                {
        !          1034:                                        /*
        !          1035:                                         * back home - phew (hopping along stream queues might
        !          1036:                                         * prove dangerous to your health)
        !          1037:                                         */
        !          1038: 
        !          1039:                                        if ((((parsestream_t *)q->q_ptr)->parse_status & PARSE_ENABLE) &&
        !          1040:                                            parse_iopps(&((parsestream_t *)q->q_ptr)->parse_io, status ? SYNC_ONE : SYNC_ZERO, &cdevent))
        !          1041:                                        {
        !          1042:                                                /*
        !          1043:                                                 * XXX - currently we do not pass up the message, as
        !          1044:                                                 * we should.
        !          1045:                                                 * for a correct behaviour wee need to block out
        !          1046:                                                 * processing until parse_iodone has been posted via
        !          1047:                                                 * a softcall-ed routine which does the message pass-up
        !          1048:                                                 * right now PPS information relies on input being
        !          1049:                                                 * received
        !          1050:                                                 */
        !          1051:                                                parse_iodone(&((parsestream_t *)q->q_ptr)->parse_io);
        !          1052:                                        }
        !          1053:                  
        !          1054:                                        if (status)
        !          1055:                                        {
        !          1056:                                                ((parsestream_t *)q->q_ptr)->parse_ppsclockev.tv = cdevent.tv;
        !          1057:                                                ++(((parsestream_t *)q->q_ptr)->parse_ppsclockev.serial);
        !          1058:                                        }
        !          1059: 
        !          1060:                                        pprintf(DD_ISR, "zs_xsisr: CD event %s has been posted for \"%s\"\n", status ? "ONE" : "ZERO", dname);
        !          1061:                                        break;
        !          1062:                                }
        !          1063:                        }
        !          1064: 
        !          1065:                        q = q->q_next;
        !          1066: 
        !          1067:                        if (!loopcheck--)
        !          1068:                        {
        !          1069:                                panic("zs_xsisr: STREAMS Queue corrupted - CD event");
        !          1070:                        }
        !          1071:                }
        !          1072: 
        !          1073:                if (cdstate)    /* fake CARRIER status - XXX currently not coordinated */
        !          1074:                  za->za_flags |= ZAS_CARR_ON;
        !          1075:                else
        !          1076:                  za->za_flags &= ~ZAS_CARR_ON;
        !          1077: 
        !          1078:                /*
        !          1079:                 * only pretend that CD and ignored transistion (SYNC,CTS)
        !          1080:                 * have been handled
        !          1081:                 */
        !          1082:                za->za_rr0 = (za->za_rr0 & ~ZSRR0_IGNORE) | (zsstatus & ZSRR0_IGNORE);
        !          1083: 
        !          1084:                if (((za->za_rr0 ^ zsstatus) & ~ZSRR0_IGNORE) == 0)
        !          1085:                {
        !          1086:                        /*
        !          1087:                         * all done - kill status indication and return
        !          1088:                         */
        !          1089:                        SCC_WRITE0(ZSWR0_RESET_STATUS); /* might kill other conditions here */
        !          1090:                        return;
        !          1091:                }
        !          1092:        }      
        !          1093: 
        !          1094:        pprintf(DD_ISR, "zs_xsisr: non CD event 0x%x for \"%s\"\n", 
        !          1095:                (za->za_rr0 ^ zsstatus) & ~ZSRR0_CD,dname);
        !          1096:        /*
        !          1097:         * we are now gathered here to process some unusual external status
        !          1098:         * interrupts.
        !          1099:         * any CD events have also been handled and shouldn't be processed
        !          1100:         * by the original routine (unless we have a VERY busy port pin)
        !          1101:         * some initializations are done here, which could have been done before for
        !          1102:         * both code paths but have been avioded for minimum path length to
        !          1103:         * the uniq_time routine
        !          1104:         */
        !          1105:        dname = (char *) 0;
        !          1106:        q = za->za_ttycommon.t_readq;
        !          1107: 
        !          1108:        loopcheck = MAXDEPTH;
        !          1109:       
        !          1110:        /*
        !          1111:         * the real thing for everything else ...
        !          1112:         */
        !          1113:        while (q)
        !          1114:        {
        !          1115:                if (q->q_qinfo && q->q_qinfo->qi_minfo)
        !          1116:                {
        !          1117:                        dname = q->q_qinfo->qi_minfo->mi_idname;
        !          1118:                        if (!strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname))
        !          1119:                        {
        !          1120:                                register void (*zsisr) (struct zscom *);
        !          1121:                  
        !          1122:                                /*
        !          1123:                                 * back home - phew (hopping along stream queues might
        !          1124:                                 * prove dangerous to your health)
        !          1125:                                 */
        !          1126:                                if ((zsisr = ((struct savedzsops *)((parsestream_t *)q->q_ptr)->parse_data)->oldzsops->zsop_xsint))
        !          1127:                                    zsisr(zs);
        !          1128:                                else
        !          1129:                                    panic("zs_xsisr: unable to locate original ISR");
        !          1130:                  
        !          1131:                                pprintf(DD_ISR, "zs_xsisr: non CD event was processed for \"%s\"\n", dname);
        !          1132:                                /*
        !          1133:                                 * now back to our program ...
        !          1134:                                 */
        !          1135:                                return;
        !          1136:                        }
        !          1137:                }
        !          1138: 
        !          1139:                q = q->q_next;
        !          1140: 
        !          1141:                if (!loopcheck--)
        !          1142:                {
        !          1143:                        panic("zs_xsisr: STREAMS Queue corrupted - non CD event");
        !          1144:                }
        !          1145:        }
        !          1146: 
        !          1147:        /*
        !          1148:         * last resort - shouldn't even come here as it indicates
        !          1149:         * corrupted TTY structures
        !          1150:         */
        !          1151:        printf("zs_zsisr: looking for \"%s\" - found \"%s\" - taking EMERGENCY path\n", parseinfo.st_rdinit->qi_minfo->mi_idname, dname ? dname : "-NIL-");
        !          1152:       
        !          1153:        if (emergencyzs && emergencyzs->zsop_xsint)
        !          1154:            emergencyzs->zsop_xsint(zs);
        !          1155:        else
        !          1156:            panic("zs_xsisr: no emergency ISR handler");
        !          1157: }
        !          1158: #endif                         /* sun */
        !          1159: 
        !          1160: /*
        !          1161:  * History:
        !          1162:  *
        !          1163:  * parsesolaris.c,v
        !          1164:  * Revision 4.11  2005/04/16 17:32:10  kardel
        !          1165:  * update copyright
        !          1166:  *
        !          1167:  * Revision 4.10  2004/11/14 16:06:08  kardel
        !          1168:  * update Id tags
        !          1169:  *
        !          1170:  * Revision 4.9  2004/11/14 15:29:41  kardel
        !          1171:  * support PPSAPI, upgrade Copyright to Berkeley style
        !          1172:  *
        !          1173:  * Revision 4.6  1998/11/15 21:56:08  kardel
        !          1174:  * ntp_memset not necessary
        !          1175:  *
        !          1176:  * Revision 4.5  1998/11/15 21:23:37  kardel
        !          1177:  * ntp_memset() replicated in Sun kernel files
        !          1178:  *
        !          1179:  * Revision 4.4  1998/06/14 21:09:40  kardel
        !          1180:  * Sun acc cleanup
        !          1181:  *
        !          1182:  * Revision 4.3  1998/06/13 12:14:59  kardel
        !          1183:  * more prototypes
        !          1184:  * fix name clashes
        !          1185:  * allow for ansi2knr
        !          1186:  *
        !          1187:  * Revision 4.2  1998/06/12 15:23:08  kardel
        !          1188:  * fix prototypes
        !          1189:  * adjust for ansi2knr
        !          1190:  *
        !          1191:  * Revision 4.1  1998/05/24 09:38:46  kardel
        !          1192:  * streams initiated iopps calls (M_xHANGUP) are now consistent with the
        !          1193:  * respective calls from zs_xsisr()
        !          1194:  * simulation of CARRIER status to avoid unecessary M_xHANGUP messages
        !          1195:  *
        !          1196:  * Revision 4.0  1998/04/10 19:45:38  kardel
        !          1197:  * Start 4.0 release version numbering
        !          1198:  *
        !          1199:  * from V3 3.28 log info deleted 1998/04/11 kardel
        !          1200:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>