Annotation of embedaddon/ntp/libparse/parsesolaris.c, revision 1.1.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>