Annotation of embedaddon/ntp/libparse/parsestreams.c, revision 1.1.1.1

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

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