📄 parsesolaris.c
字号:
*mp = (*mp)->b_cont; freeb(mmp); } } return (unsigned long)~0;}/* * convert incoming data */static intparserput( queue_t *q, mblk_t *imp ){ register unsigned char type; mblk_t *mp = imp; switch (type = mp->b_datap->db_type) { default: /* * anything we don't know will be put on queue * the service routine will move it to the next one */ pprintf(DD_RPUT, "parse: parserput - forward type 0x%x\n", type); if (canputnext(q) || (mp->b_datap->db_type > QPCTL)) { putnext(q, mp); } else putq(q, mp); break; case M_BREAK: case M_DATA: { register parsestream_t * parse = (parsestream_t *)q->q_ptr; register mblk_t *nmp; register unsigned long ch; timestamp_t ctime; timespec_t hres_time; /* * get time on packet delivery */ gethrestime(&hres_time); ctime.tv.tv_sec = hres_time.tv_sec; ctime.tv.tv_usec = hres_time.tv_nsec / 1000; if (!(parse->parse_status & PARSE_ENABLE)) { pprintf(DD_RPUT, "parse: parserput - parser disabled - forward type 0x%x\n", type); if (canputnext(q) || (mp->b_datap->db_type > QPCTL)) { putnext(q, mp); } else putq(q, mp); } else { pprintf(DD_RPUT, "parse: parserput - M_%s\n", (type == M_DATA) ? "DATA" : "BREAK"); if (type == M_DATA) { /* * parse packet looking for start an end characters */ while (mp != (mblk_t *)NULL) { ch = rdchar(&mp); if (ch != ~0 && parse_ioread(&parse->parse_io, (unsigned int)ch, &ctime)) { /* * up up and away (hopefully ...) * don't press it if resources are tight or nobody wants it */ nmp = (mblk_t *)NULL; if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) { bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); nmp->b_wptr += sizeof(parsetime_t); putnext(parse->parse_queue, nmp); } else if (nmp) freemsg(nmp); parse_iodone(&parse->parse_io); } } } else { if (parse_ioread(&parse->parse_io, (unsigned int)0, &ctime)) { /* * up up and away (hopefully ...) * don't press it if resources are tight or nobody wants it */ nmp = (mblk_t *)NULL; if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) { bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); nmp->b_wptr += sizeof(parsetime_t); putnext(parse->parse_queue, nmp); } else if (nmp) freemsg(nmp); parse_iodone(&parse->parse_io); } freemsg(mp); } break; } } /* * CD PPS support for non direct ISR hack */ case M_HANGUP: case M_UNHANGUP: { register parsestream_t * parse = (parsestream_t *)q->q_ptr; timestamp_t ctime; timespec_t hres_time; register mblk_t *nmp; register int status = cd_invert ^ (type == M_UNHANGUP); gethrestime(&hres_time); ctime.tv.tv_sec = hres_time.tv_sec; ctime.tv.tv_usec = hres_time.tv_nsec / 1000; pprintf(DD_RPUT, "parse: parserput - M_%sHANGUP\n", (type == M_HANGUP) ? "" : "UN"); if ((parse->parse_status & PARSE_ENABLE) && parse_iopps(&parse->parse_io, status ? SYNC_ONE : SYNC_ZERO, &ctime)) { nmp = (mblk_t *)NULL; if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) { bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); nmp->b_wptr += sizeof(parsetime_t); putnext(parse->parse_queue, nmp); } else if (nmp) freemsg(nmp); parse_iodone(&parse->parse_io); freemsg(mp); } else if (canputnext(q) || (mp->b_datap->db_type > QPCTL)) { putnext(q, mp); } else putq(q, mp); if (status) { parse->parse_ppsclockev.tv = ctime.tv; ++(parse->parse_ppsclockev.serial); } } } return 0;}static int init_zs_linemon P((queue_t *, queue_t *)); /* handle line monitor for "zs" driver */static void close_zs_linemon P((queue_t *, queue_t *));/*-------------------- CD isr status monitor ---------------*/static intinit_linemon( queue_t *q ){ register queue_t *dq; dq = WR(q); /* * we ARE doing very bad things down here (basically stealing ISR * hooks) * * so we chase down the STREAMS stack searching for the driver * and if this is a known driver we insert our ISR routine for * status changes in to the ExternalStatus handling hook */ while (dq->q_next) { dq = dq->q_next; /* skip down to driver */ } /* * find appropriate driver dependent routine */ if (dq->q_qinfo && dq->q_qinfo->qi_minfo) { register char *dname = dq->q_qinfo->qi_minfo->mi_idname; pprintf(DD_INSTALL, "init_linemon: driver is \"%s\"\n", dname);#ifdef sun if (dname && !strcmp(dname, "zs")) { return init_zs_linemon(dq, q); } else#endif { pprintf(DD_INSTALL, "init_linemon: driver \"%s\" not suitable for CD monitoring\n", dname); return 0; } } pprintf(DD_INSTALL, "init_linemon: cannot find driver\n"); return 0;}static voidclose_linemon( queue_t *q, queue_t *my_q ){ /* * find appropriate driver dependent routine */ if (q->q_qinfo && q->q_qinfo->qi_minfo) { register char *dname = q->q_qinfo->qi_minfo->mi_idname;#ifdef sun if (dname && !strcmp(dname, "zs")) { close_zs_linemon(q, my_q); return; } pprintf(DD_INSTALL, "close_linemon: cannot find driver close routine for \"%s\"\n", dname);#endif } pprintf(DD_INSTALL, "close_linemon: cannot find driver name\n");}#ifdef sun#include <sys/tty.h>#include <sys/zsdev.h>#include <sys/ser_async.h>#include <sys/ser_zscc.h>static void zs_xsisr P((struct zscom *)); /* zs external status interupt handler *//* * there should be some docs telling how to get to * sz:zs_usec_delay and zs:initzsops() */#define zs_usec_delay 5struct savedzsops{ struct zsops zsops; struct zsops *oldzsops;};static struct zsops *emergencyzs;static intinit_zs_linemon( queue_t *q, queue_t *my_q ){ register struct zscom *zs; register struct savedzsops *szs; register parsestream_t *parsestream = (parsestream_t *)my_q->q_ptr; /* * we expect the zsaline pointer in the q_data pointer * from there on we insert our on EXTERNAL/STATUS ISR routine * into the interrupt path, before the standard handler */ zs = ((struct asyncline *)q->q_ptr)->za_common; if (!zs) { /* * well - not found on startup - just say no (shouldn't happen though) */ return 0; } else { /* * we do a direct replacement, in case others fiddle also * if somebody else grabs our hook and we disconnect * we are in DEEP trouble - panic is likely to be next, sorry */ szs = (struct savedzsops *) kmem_alloc(sizeof(struct savedzsops), KM_SLEEP); if (szs == (struct savedzsops *)0) { pprintf(DD_INSTALL, "init_zs_linemon: CD monitor NOT installed - no memory\n"); return 0; } else { parsestream->parse_data = (void *)szs; mutex_enter(zs->zs_excl); parsestream->parse_dqueue = q; /* remember driver */ szs->zsops = *zs->zs_ops; szs->zsops.zsop_xsint = (void (*) P((struct zscom *)))zs_xsisr; /* place our bastard */ szs->oldzsops = zs->zs_ops; emergencyzs = zs->zs_ops; zs->zs_ops = &szs->zsops; /* hook it up */ /* * XXX: this is usually done via zsopinit() * - have yet to find a way to call that routine */ zs->zs_xsint = (void (*) P((struct zscom *)))zs_xsisr; mutex_exit(zs->zs_excl); pprintf(DD_INSTALL, "init_zs_linemon: CD monitor installed\n"); return 1; } }}/* * unregister our ISR routine - must call under splhigh() (or * whatever block ZS status interrupts) */static voidclose_zs_linemon( queue_t *q, queue_t *my_q ){ register struct zscom *zs; register parsestream_t *parsestream = (parsestream_t *)my_q->q_ptr; zs = ((struct asyncline *)q->q_ptr)->za_common; if (!zs) { /* * well - not found on startup - just say no (shouldn't happen though) */ return; } else { register struct savedzsops *szs = (struct savedzsops *)parsestream->parse_data; mutex_enter(zs->zs_excl); zs->zs_ops = szs->oldzsops; /* reset to previous handler functions */ /* * XXX: revert xsint (usually done via zsopinit() - have still to find * a way to call that bugger */ zs->zs_xsint = zs->zs_ops->zsop_xsint; mutex_exit(zs->zs_excl); kmem_free((caddr_t)szs, sizeof (struct savedzsops)); pprintf(DD_INSTALL, "close_zs_linemon: CD monitor deleted\n"); return; }}#define ZSRR0_IGNORE (ZSRR0_CD|ZSRR0_SYNC|ZSRR0_CTS)#define MAXDEPTH 50 /* maximum allowed stream crawl *//* * take external status interrupt (only CD interests us) */static voidzs_xsisr( struct zscom *zs ){ register struct asyncline *za = (struct asyncline *)zs->zs_priv; register queue_t *q; register unsigned char zsstatus; register int loopcheck; register unsigned char cdstate; register const char *dname = "-UNKNOWN-"; timespec_t hres_time; /* * pick up current state */ zsstatus = SCC_READ0(); if (za->za_rr0 ^ (cdstate = zsstatus & ZSRR0_CD)) { timestamp_t cdevent; register int status; /* * time stamp */ gethrestime(&hres_time); cdevent.tv.tv_sec = hres_time.tv_sec; cdevent.tv.tv_usec = hres_time.tv_nsec / 1000; q = za->za_ttycommon.t_readq; /* * logical state */ status = cd_invert ? cdstate == 0 : cdstate != 0; /* * ok - now the hard part - find ourself */ loopcheck = MAXDEPTH; while (q) { if (q->q_qinfo && q->q_qinfo->qi_minfo) { dname = q->q_qinfo->qi_minfo->mi_idname; if (!strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname)) { /* * back home - phew (hopping along stream queues might * prove dangerous to your health) */ if ((((parsestream_t *)q->q_ptr)->parse_status & PARSE_ENABLE) && parse_iopps(&((parsestream_t *)q->q_ptr)->parse_io, status ? SYNC_ONE : SYNC_ZERO, &cdevent)) { /* * XXX - currently we do not pass up the message, as * we should. * for a correct behaviour wee need to block out * processing until parse_iodone has been posted via * a softcall-ed routine which does the message pass-up * right now PPS information relies on input being * received */ parse_iodone(&((parsestream_t *)q->q_ptr)->parse_io); } if (status) { ((parsestream_t *)q->q_ptr)->parse_ppsclockev.tv = cdevent.tv; ++(((parsestream_t *)q->q_ptr)->parse_ppsclockev.serial); } pprintf(DD_ISR, "zs_xsisr: CD event %s has been posted for \"%s\"\n", status ? "ONE" : "ZERO", dname); break; } } q = q->q_next; if (!loopcheck--) { panic("zs_xsisr: STREAMS Queue corrupted - CD event"); } } if (cdstate) /* fake CARRIER status - XXX currently not coordinated */ za->za_flags |= ZAS_CARR_ON; else za->za_flags &= ~ZAS_CARR_ON; /* * only pretend that CD and ignored transistion (SYNC,CTS) * have been handled */ za->za_rr0 = (za->za_rr0 & ~ZSRR0_IGNORE) | (zsstatus & ZSRR0_IGNORE); if (((za->za_rr0 ^ zsstatus) & ~ZSRR0_IGNORE) == 0) { /* * all done - kill status indication and return */ SCC_WRITE0(ZSWR0_RESET_STATUS); /* might kill other conditions here */ return; } } pprintf(DD_ISR, "zs_xsisr: non CD event 0x%x for \"%s\"\n", (za->za_rr0 ^ zsstatus) & ~ZSRR0_CD,dname); /* * we are now gathered here to process some unusual external status * interrupts. * any CD events have also been handled and shouldn't be processed * by the original routine (unless we have a VERY busy port pin) * some initializations are done here, which could have been done before for * both code paths but have been avioded for minimum path length to * the uniq_time routine */ dname = (char *) 0; q = za->za_ttycommon.t_readq; loopcheck = MAXDEPTH; /* * the real thing for everything else ... */ while (q) { if (q->q_qinfo && q->q_qinfo->qi_minfo) { dname = q->q_qinfo->qi_minfo->mi_idname; if (!strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname)) { register void (*zsisr) P((struct zscom *)); /* * back home - phew (hopping along stream queues might * prove dangerous to your health) */ if ((zsisr = ((struct savedzsops *)((parsestream_t *)q->q_ptr)->parse_data)->oldzsops->zsop_xsint)) zsisr(zs); else panic("zs_xsisr: unable to locate original ISR"); pprintf(DD_ISR, "zs_xsisr: non CD event was processed for \"%s\"\n", dname); /* * now back to our program ... */ return; } } q = q->q_next; if (!loopcheck--) { panic("zs_xsisr: STREAMS Queue corrupted - non CD event"); } } /* * last resort - shouldn't even come here as it indicates * corrupted TTY structures */ printf("zs_zsisr: looking for \"%s\" - found \"%s\" - taking EMERGENCY path\n", parseinfo.st_rdinit->qi_minfo->mi_idname, dname ? dname : "-NIL-"); if (emergencyzs && emergencyzs->zsop_xsint) emergencyzs->zsop_xsint(zs); else panic("zs_xsisr: no emergency ISR handler");}#endif /* sun *//* * History: * * parsesolaris.c,v * Revision 4.11 2005/04/16 17:32:10 kardel * update copyright * * Revision 4.10 2004/11/14 16:06:08 kardel * update Id tags * * Revision 4.9 2004/11/14 15:29:41 kardel * support PPSAPI, upgrade Copyright to Berkeley style * * Revision 4.6 1998/11/15 21:56:08 kardel * ntp_memset not necessary * * Revision 4.5 1998/11/15 21:23:37 kardel * ntp_memset() replicated in Sun kernel files * * Revision 4.4 1998/06/14 21:09:40 kardel * Sun acc cleanup * * Revision 4.3 1998/06/13 12:14:59 kardel * more prototypes * fix name clashes * allow for ansi2knr * * Revision 4.2 1998/06/12 15:23:08 kardel * fix prototypes * adjust for ansi2knr * * Revision 4.1 1998/05/24 09:38:46 kardel * streams initiated iopps calls (M_xHANGUP) are now consistent with the * respective calls from zs_xsisr() * simulation of CARRIER status to avoid unecessary M_xHANGUP messages * * Revision 4.0 1998/04/10 19:45:38 kardel * Start 4.0 release version numbering * * from V3 3.28 log info deleted 1998/04/11 kardel */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -