diff options
Diffstat (limited to 'usr.sbin/xntpd/kernel/tty_chu_STREAMS.c')
-rw-r--r-- | usr.sbin/xntpd/kernel/tty_chu_STREAMS.c | 603 |
1 files changed, 0 insertions, 603 deletions
diff --git a/usr.sbin/xntpd/kernel/tty_chu_STREAMS.c b/usr.sbin/xntpd/kernel/tty_chu_STREAMS.c deleted file mode 100644 index f46e25d..0000000 --- a/usr.sbin/xntpd/kernel/tty_chu_STREAMS.c +++ /dev/null @@ -1,603 +0,0 @@ -/* - * CHU STREAMS module for SunOS - * - * Version 2.6 - * - * Copyright 1991-1994, Nick Sayer - * - * Special thanks to Greg Onufer for his debug assists. - * Special thanks to Matthias Urlichs for the 4.1.x loadable driver support - * code. - * Special wet-noodle whippings to Sun for not properly documenting - * ANYTHING that makes this stuff at all possible. - * - * Should be PUSHed directly on top of a serial I/O channel. - * Provides complete chucode structures to user space. - * - * COMPILATION: - * - * - * To make a SunOS 4.1.x compatable loadable module (from the ntp kernel - * directory): - * - * % cc -c -I../include -DLOADABLE tty_chu_STREAMS.c - * - * The resulting .o file is the loadable module. Modload it - * thusly: - * - * % modload tty_chu_STREAMS.o -entry _chuinit - * - * When none of the instances are pushed in a STREAM, you can - * modunload the driver in the usual manner if you wish. - * - * As an alternative to loading it dynamically you can compile it - * directly into the kernel by hacking str_conf.c. See the README - * file for more details on doing it the old fashioned way. - * - * - * To make a Solaris 2.x compatable module (from the ntp kernel - * directory): - * - * % {gcc,cc} -c -I../include -DSOLARIS2 tty_chu_STREAMS.c - * % ld -r -o /usr/kernel/strmod/chu tty_chu_STREAMS.o - * % chmod 755 /usr/kernel/strmod/chu - * - * The OS will load it for you automagically when it is first pushed. - * - * If you get syntax errors from <sys/timer.h> (really references - * to types that weren't typedef'd in gcc's version of types.h), - * add -D_SYS_TIMER_H to blot out the miscreants. - * - * Under Solaris 2.2 and previous, do not attempt to modunload the - * module unless you're SURE it's not in use. I haven't tried it, but - * I've been told it won't do the right thing. Under Solaris 2.3 (and - * presumably future revs) an attempt to unload the module when it's in - * use will properly refuse with a "busy" message. - * - * - * HISTORY: - * - * v2.6 - Mutexed the per-instance chucode just to be safe. - * v2.5 - Fixed show-stopper bug in Solaris 2.x - qprocson(). - * v2.4 - Added dynamic allocation support for Solaris 2.x. - * v2.3 - Added support for Solaris 2.x. - * v2.2 - Added SERVICE IMMEDIATE hack. - * v2.1 - Added 'sixth byte' heuristics. - * v2.0 - first version with an actual version number. - * Added support for new CHU 'second 31' data format. - * Deleted PEDANTIC and ANAL_RETENTIVE. - * - */ - -#ifdef SOLARIS2 -# ifndef NCHU -# define NCHU 1 -# endif -# define _KERNEL -#elif defined(LOADABLE) -# ifndef NCHU -# define NCHU 3 -# define KERNEL -# endif -#else -# include "chu.h" -#endif - -#if NCHU > 0 - -/* - * Number of microseconds we allow between - * character arrivals. The speed is 300 baud - * so this should be somewhat more than 30 msec - */ -#define CHUMAXUSEC (60*1000) /* 60 msec */ - -#include <sys/types.h> -#include <sys/stream.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/errno.h> -#include <sys/user.h> -#include <syslog.h> -#include <sys/tty.h> - -#include <sys/chudefs.h> - -#ifdef SOLARIS2 - -#include <sys/ksynch.h> -#include <sys/kmem.h> -#include <sys/cmn_err.h> -#include <sys/conf.h> -#include <sys/strtty.h> -#include <sys/modctl.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> - -#endif - -#ifdef LOADABLE - -#include <sys/kernel.h> -#include <sys/conf.h> -#include <sys/buf.h> -#include <sundev/mbvar.h> -#include <sun/autoconf.h> -#include <sun/vddrv.h> - -#endif - - -static struct module_info rminfo = { 0, "chu", 0, INFPSZ, 0, 0 }; -static struct module_info wminfo = { 0, "chu", 0, INFPSZ, 0, 0 }; -static int chuopen(), churput(), chuwput(), chuclose(); - -static struct qinit rinit = { churput, NULL, chuopen, chuclose, NULL, - &rminfo, NULL }; - -static struct qinit winit = { chuwput, NULL, NULL, NULL, NULL, - &wminfo, NULL }; - -struct streamtab chuinfo = { &rinit, &winit, NULL, NULL }; - -/* - * Here's our private data type and structs - */ -struct priv_data -{ -#ifdef SOLARIS2 - kmutex_t chucode_mutex; -#else - char in_use; -#endif - struct chucode chu_struct; -}; - -#ifndef SOLARIS2 -struct priv_data our_priv_data[NCHU]; -#endif - -#ifdef SOLARIS2 - -static struct fmodsw fsw = -{ - "chu", - &chuinfo, - D_NEW | D_MP -}; - -extern struct mod_ops mod_strmodops; - -static struct modlstrmod modlstrmod = -{ - &mod_strmodops, - "CHU timecode decoder v2.6", - &fsw -}; - -static struct modlinkage modlinkage = -{ - MODREV_1, - (void*) &modlstrmod, - NULL -}; - -int _init() -{ - return mod_install(&modlinkage); -} - -int _info(foo) -struct modinfo *foo; -{ - return mod_info(&modlinkage,foo); -} - -int _fini() -{ - return mod_remove(&modlinkage); -} - -#endif /* SOLARIS2 */ - -#ifdef LOADABLE - -# ifdef sun - -static struct vdldrv vd = -{ - VDMAGIC_PSEUDO, - "chu", - NULL, NULL, NULL, 0, 0, NULL, NULL, 0, 0, -}; - -static struct fmodsw *chu_fmod; - -/*ARGSUSED*/ -chuinit (fc, vdp, vdi, vds) - unsigned int fc; - struct vddrv *vdp; - addr_t vdi; - struct vdstat *vds; -{ - switch (fc) { - case VDLOAD: - { - int dev, i; - - /* Find free entry in fmodsw */ - for (dev = 0; dev < fmodcnt; dev++) { - if (fmodsw[dev].f_str == NULL) - break; - } - if (dev == fmodcnt) - return (ENODEV); - chu_fmod = &fmodsw[dev]; - - /* If you think a kernel would have strcpy() you're mistaken. */ - for (i = 0; i <= FMNAMESZ; i++) - chu_fmod->f_name[i] = wminfo.mi_idname[i]; - - chu_fmod->f_str = &chuinfo; - } - vdp->vdd_vdtab = (struct vdlinkage *) & vd; - - { - int i; - - for (i=0; i<NCHU; i++) - our_priv_data[i].in_use=0; - } - - return 0; - case VDUNLOAD: - { - int dev; - - for (dev = 0; dev < NCHU; dev++) - if (our_priv_data[dev].in_use) { - /* One of the modules is still open */ - return (EBUSY); - } - } - chu_fmod->f_name[0] = '\0'; - chu_fmod->f_str = NULL; - return 0; - case VDSTAT: - return 0; - default: - return EIO; - } -} - -# endif /* sun */ - -#endif /* LOADABLE */ - -#if !defined(LOADABLE) && !defined(SOLARIS2) - -char chu_first_open=1; - -#endif - -/*ARGSUSED*/ -static int chuopen(q, dev, flag, sflag) -queue_t *q; -dev_t dev; -int flag; -int sflag; -{ - int i; - -#if !defined(LOADABLE) && !defined(SOLARIS2) - if (chu_first_open) - { - chu_first_open=0; - - for(i=0;i<NCHU;i++) - our_priv_data[i].in_use=0; - } -#endif - -#ifdef SOLARIS2 - /* According to the docs, calling with KM_SLEEP can never - fail */ - - q->q_ptr = kmem_alloc( sizeof(struct priv_data), KM_SLEEP ); - ((struct priv_data *) q->q_ptr)->chu_struct.ncodechars = 0; - - mutex_init(&((struct priv_data *) q->q_ptr)->chucode_mutex,"Chucode Mutex",MUTEX_DRIVER,NULL); - qprocson(q); - - if (!putnextctl1(WR(q), M_CTL, MC_SERVICEIMM)) - { - qprocsoff(q); - mutex_destroy(&((struct priv_data *)q->q_ptr)->chucode_mutex); - kmem_free(q->q_ptr, sizeof(struct chucode) ); - return (EFAULT); - } - - return 0; - -#else - for(i=0;i<NCHU;i++) - if (!our_priv_data[i].in_use) - { - ((struct priv_data *) (q->q_ptr))=&(our_priv_data[i]); - our_priv_data[i].in_use++; - our_priv_data[i].chu_struct.ncodechars = 0; - if (!putctl1(WR(q)->q_next, M_CTL, MC_SERVICEIMM)) - { - our_priv_data[i].in_use=0; - u.u_error = EFAULT; - return (OPENFAIL); - } - return 0; - } - - u.u_error = EBUSY; - return (OPENFAIL); -#endif - -} - -/*ARGSUSED*/ -static int chuclose(q, flag) -queue_t *q; -int flag; -{ -#ifdef SOLARIS2 - qprocsoff(q); - mutex_destroy(&((struct priv_data *)q->q_ptr)->chucode_mutex); - kmem_free(q->q_ptr, sizeof(struct chucode) ); -#else - ((struct priv_data *) (q->q_ptr))->in_use=0; -#endif - return (0); -} - -/* - * Now the crux of the biscuit. - * - * We will be passed data from the man downstairs. If it's not a data - * packet, it must be important, so pass it along unmunged. If, however, - * it is a data packet, we're gonna do special stuff to it. We're going - * to pass each character we get to the old line discipline code we - * include below for just such an occasion. When the old ldisc code - * gets a full chucode struct, we'll hand it back upstairs. - * - * chuinput takes a single character and q (as quickly as possible). - * passback takes a pointer to a chucode struct and q and sends it upstream. - */ - -void chuinput(); -void passback(); - -static int churput(q, mp) -queue_t *q; -mblk_t *mp; -{ - mblk_t *bp; - - switch(mp->b_datap->db_type) - { - case M_DATA: - for(bp=mp; bp!=NULL; bp=bp->b_cont) - { - while(bp->b_rptr < bp->b_wptr) - chuinput( ((u_char)*(bp->b_rptr++)) , q ); - } - freemsg(mp); - break; - default: - putnext(q,mp); - break; - } - -} - -/* - * Writing to a chu device doesn't make sense, but we'll pass them - * through in case they're important. - */ - -static int chuwput(q, mp) -queue_t *q; -mblk_t *mp; -{ - putnext(q,mp); -} - -/* - * Take a pointer to a filled chucode struct and a queue and - * send the chucode stuff upstream - */ - -void passback(outdata,q) -struct chucode *outdata; -queue_t *q; -{ - mblk_t *mp; - int j; - - mp=(mblk_t*) allocb(sizeof(struct chucode),BPRI_LO); - - if (mp==NULL) - { -#ifdef SOLARIS2 - cmn_err(CE_WARN,"chu module couldn't allocate message block"); -#else - log(LOG_ERR,"chu: cannot allocate message"); -#endif - return; - } - - for(j=0;j<sizeof(struct chucode); j++) - *mp->b_wptr++ = *( ((char*)outdata) + j ); - - putnext(q,mp); -} - -/* - * This routine was copied nearly verbatim from the old line discipline. - */ -void chuinput(c,q) -register u_char c; -queue_t *q; -{ - register struct chucode *chuc; - register int i; - long sec, usec; - struct timeval tv; - - /* - * Quick, Batman, get a timestamp! We need to do this - * right away. The time between the end of the stop bit - * and this point is critical, and should be as nearly - * constant and as short as possible. (Un)fortunately, - * the Sun's clock granularity is so big this isn't a - * major problem. - * - * uniqtime() is totally undocumented, but there you are. - */ - uniqtime(&tv); - -#ifdef SOLARIS2 - mutex_enter(&((struct priv_data *)q->q_ptr)->chucode_mutex); -#endif - - /* - * Now, locate the chu struct once so we don't have to do it - * over and over. - */ - chuc=&(((struct priv_data *) (q->q_ptr))->chu_struct); - - /* - * Compute the difference in this character's time stamp - * and the last. If it exceeds the margin, blow away all - * the characters currently in the buffer. - */ - i = (int)chuc->ncodechars; - if (i > 0) - { - sec = tv.tv_sec - chuc->codetimes[i-1].tv_sec; - usec = tv.tv_usec - chuc->codetimes[i-1].tv_usec; - if (usec < 0) - { - sec -= 1; - usec += 1000000; - } - if (sec != 0 || usec > CHUMAXUSEC) - { - i = 0; - chuc->ncodechars = 0; - } - } - - /* - * Store the character. - */ - chuc->codechars[i] = (u_char)c; - chuc->codetimes[i] = tv; - - /* - * Now we perform the 'sixth byte' heuristics. - * - * This is a long story. - * - * We used to be able to count on the first byte of the code - * having a '6' in the LSD. This prevented most code framing - * errors (garbage before the first byte wouldn't typically - * have a 6 in the LSD). That's no longer the case. - * - * We can get around this, however, by noting that the 6th byte - * must be either equal to or one's complement of the first. - * If we get a sixth byte that ISN'T like that, then it may - * well be that the first byte is garbage. The right thing - * to do is to left-shift the whole buffer one count and - * continue to wait for the sixth byte. - */ - if (i == NCHUCHARS/2) - { - register u_char temp_byte; - - temp_byte=chuc->codechars[i] ^ chuc->codechars[0]; - - if ( (temp_byte) && (temp_byte!=0xff) ) - { - register int t; - /* - * No match. Left-shift the buffer and try again - */ - for(t=0;t<=NCHUCHARS/2;t++) - { - chuc->codechars[t]=chuc->codechars[t+1]; - chuc->codetimes[t]=chuc->codetimes[t+1]; - } - - i--; /* This is because of the ++i immediately following */ - } - } - - /* - * We done yet? - */ - if (++i < NCHUCHARS) - { - /* - * We're not done. Not much to do here. Save the count and wait - * for another character. - */ - chuc->ncodechars = (u_char)i; - } - else - { - /* - * We are done. Mark this buffer full and pass it along. - */ - chuc->ncodechars = NCHUCHARS; - - /* - * Now we have a choice. Either the front half and back half - * have to match, or be one's complement of each other. - * - * So let's try the first byte and see - */ - - if(chuc->codechars[0] == chuc->codechars[NCHUCHARS/2]) - { - chuc->chutype = CHU_TIME; - for( i=0; i<(NCHUCHARS/2); i++) - if (chuc->codechars[i] != chuc->codechars[i+(NCHUCHARS/2)]) - { - chuc->ncodechars = 0; -#ifdef SOLARIS2 - mutex_exit(&((struct priv_data *)q->q_ptr)->chucode_mutex); -#endif - return; - } - } - else - { - chuc->chutype = CHU_YEAR; - for( i=0; i<(NCHUCHARS/2); i++) - if (((chuc->codechars[i] ^ chuc->codechars[i+(NCHUCHARS/2)]) & 0xff) - != 0xff ) - { - chuc->ncodechars = 0; -#ifdef SOLARIS2 - mutex_exit(&((struct priv_data *)q->q_ptr)->chucode_mutex); -#endif - return; - } - } - - passback(chuc,q); /* We're done! */ - chuc->ncodechars = 0; /* Start all over again! */ - } -#ifdef SOLARIS2 - mutex_exit(&((struct priv_data *)q->q_ptr)->chucode_mutex); -#endif -} - -#endif /* NCHU > 0 */ |